You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Swift:如何让枚举返回不同的视图控制器类实例?

用枚举简化UIViewController的实例化操作

当然可以!用枚举来封装视图控制器的实例化逻辑绝对是个非常优雅的解决方案,能帮你彻底摆脱重复的样板代码,还让代码更易维护、更安全。我来一步步给你演示怎么实现:

第一步:定义关联标识符的枚举

首先,咱们创建一个枚举,把每个视图控制器对应的storyboard标识符作为枚举case的原始值:

enum ViewControllerType: String {
    // 每个case的rawValue对应storyboard里的控制器标识符
    case placeArea = "PlaceAreaC"
    case notification = "NotificationC"
    // 后续新增控制器直接在这里加case就行
}

第二步:给枚举添加实例化方法

接下来给这个枚举扩展一个方法,把重复的UIStoryboard实例化逻辑封装进去,还可以做类型安全的转换,避免强制解包的风险:

extension ViewControllerType {
    /// 实例化对应的视图控制器,默认从Main.storyboard加载
    /// - Parameters:
    ///   - storyboard: 目标storyboard名称,默认是"Main"
    /// - Returns: 类型转换后的视图控制器,转换失败会触发fatalError(也可以改成返回可选值)
    func instantiate<T: UIViewController>(from storyboard: String = "Main") -> T {
        let storyboard = UIStoryboard(name: storyboard, bundle: nil)
        guard let viewController = storyboard.instantiateViewController(withIdentifier: rawValue) as? T else {
            fatalError("⚠️ 无法实例化标识符为\(rawValue)的控制器,或者类型转换为\(T.self)失败!")
        }
        return viewController
    }
}

第三步:使用枚举快速实例化控制器

现在你只需要一行代码就能完成实例化,而且类型安全,再也不用重复写那些冗长的storyboard代码了:

// 实例化PlaceAreaC
let placeAreaC: PlaceAreaC = ViewControllerType.placeArea.instantiate()

// 实例化NotificationC
let notificationC: NotificationC = ViewControllerType.notification.instantiate()

// 如果控制器在其他storyboard里,直接传名称就行
// let otherVC: OtherVC = ViewControllerType.other.instantiate(from: "OtherStoryboard")

进阶:支持多Storyboard的关联值写法

如果你的项目里控制器分散在多个storyboard中,还可以用枚举的关联值来绑定对应的storyboard名称,让逻辑更清晰:

enum ViewControllerType {
    case placeArea
    case notification
    case settings // 这个控制器在Settings.storyboard里
    
    // 给每个case绑定对应的标识符和storyboard名称
    var info: (identifier: String, storyboard: String) {
        switch self {
        case .placeArea:
            return ("PlaceAreaC", "Main")
        case .notification:
            return ("NotificationC", "Main")
        case .settings:
            return ("SettingsC", "Settings")
        }
    }
}

extension ViewControllerType {
    func instantiate<T: UIViewController>() -> T {
        let storyboard = UIStoryboard(name: info.storyboard, bundle: nil)
        guard let viewController = storyboard.instantiateViewController(withIdentifier: info.identifier) as? T else {
            fatalError("⚠️ 实例化失败:标识符\(info.identifier),目标类型\(T.self)")
        }
        return viewController
    }
}

使用的时候更省心,不用手动传storyboard名称:

let settingsC: SettingsC = ViewControllerType.settings.instantiate()

为什么这么做?

  • 减少冗余代码:再也不用重复写UIStoryboard(name: ...)这一串代码
  • 集中管理标识符:所有控制器的storyboard标识符都存在枚举里,修改起来更方便
  • 类型安全:枚举case是编译时检查的,避免拼写错误导致的运行时崩溃
  • 可读性更强:ViewControllerType.placeArea.instantiate()比冗长的实例化代码更直观

内容的提问来源于stack exchange,提问作者user1591668

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:04:32