如何让变量可接收所有UIViewController子类实例
问题原因
你的第一种写法报错有两个核心问题:
- 赋值时直接写
ZeroViewController/OneViewController是引用类的元类型,没有加()调用构造方法生成控制器实例,本身就不符合present方法需要传入控制器实例的要求 - Swift是类型安全语言,如果不显式指定变量类型,switch分支内会默认把赋值对象推断为对应控制器的具体子类类型,和你提前声明的
UIViewController父类类型产生类型匹配冲突
方案1:修正原有switch写法(改动最小)
只需要补全实例化的(),确保变量类型明确声明为UIViewController,再加个兜底分支处理非法索引即可,不需要每个分支单独写present逻辑:
func openController(index: Int){ let viewController: UIViewController switch index { case 0: viewController = ZeroViewController() case 1: viewController = OneViewController() // 按顺序补全case 2到case 11即可 default: // 索引不合法时直接返回,避免崩溃 return } self.present(viewController, animated: true) }
方案2:构造器数组映射(更精简,易维护)
如果按钮索引和控制器是固定一一对应的关系,可以完全去掉switch语句,用数组按索引顺序存对应控制器的构造闭包,代码更短,后续调整对应关系只需要改数组顺序:
// 按按钮索引顺序,存放对应控制器的构造逻辑 private let controllerBuilders: [() -> UIViewController] = [ { ZeroViewController() }, { OneViewController() }, // 按顺序补全剩余10个控制器的构造逻辑即可 ] func openController(index: Int){ // 先校验索引合法性,避免数组越界崩溃 guard controllerBuilders.indices.contains(index) else { return } let targetVC = controllerBuilders[index]() self.present(targetVC, animated: true) }
如果你的控制器是通过Storyboard、Xib初始化的,只需要把数组闭包里的代码替换成对应实例化逻辑即可,整体逻辑不需要改动。
内容的提问来源于stack exchange,提问作者KANAYO AUGUSTIN UG
相关产品推荐
相关产品推荐

