如何复用单个Storyboard适配多视图控制器,避免重复编写代码?
可用实现方案
你此前尝试的继承思路完全可用,不需要复制Storyboard,结合正确的Storyboard配置即可实现零重复代码,除此之外还有两类更灵活的实现方案可选:
方案1:继承+单场景Storyboard配置(最贴合你现有代码)
仅保留1份绑定基类FirstViewController的Storyboard场景,所有通用outlet、布局、TableView配置、业务逻辑都在基类中实现,需要差异化的逻辑提前暴露为可重写的方法/属性即可,比如数据模型属性、自定义Cell配置方法等。
- 支持iOS 13及以上版本的场景,可直接使用
instantiateViewController(identifier:creator:)方法指定要初始化的子类,所有outlet会自动继承绑定,无需重复连线:
// 实例化SecondViewController示例 let commonSB = UIStoryboard(name: "你的Storyboard文件名", bundle: nil) let secondVC = commonSB.instantiateViewController(identifier: "公共场景的Storyboard ID") { coder in return SecondViewController(coder: coder) } // 后续正常使用secondVC即可
- 若需要兼容iOS 13以下版本,可在实例化基类VC后通过runtime修改类类型为子类(注意子类不要新增存储属性,避免内存异常):
let commonSB = UIStoryboard(name: "你的Storyboard文件名", bundle: nil) let secondVC = commonSB.instantiateViewController(withIdentifier: "公共场景的Storyboard ID") object_setClass(secondVC, SecondViewController.self)
方案2:子ViewController封装(耦合度最低,扩展性最强)
如果不想用继承,可将通用逻辑完全抽离为独立的公共VC:
- 单独写1个
CommonContentViewController,绑定唯一的Storyboard场景,所有通用布局、逻辑、outlet都在这个类中实现,对外暴露数据协议属性:
// 公共数据协议,三个场景各自实现即可 protocol CommonDataProvidable { var listData: [CommonItemModel] { get } // 其他需要差异化的属性/方法 } class CommonContentViewController: UIViewController { var dataProvider: CommonDataProvidable! // 所有通用逻辑,数据都从dataProvider取 }
- 三个业务场景对应的ViewController不需要写任何布局相关代码,只需要将公共VC作为子VC添加到自身视图中,占满全屏,再传入对应实现的
dataProvider即可,差异逻辑直接在各自的父VC中实现即可。
方案3:单VC+场景类型枚举(代码量最少)
如果三个场景的差异仅在数据模型,没有需要重写的特殊逻辑,可以完全不用写三个子类:
- 定义场景枚举,在枚举中绑定不同的数据模型
- 所有场景复用同一个VC类,实例化时传入对应场景类型即可:
enum CommonSceneType { case first, second, third var targetData: [CommonItemModel] { // 返回对应场景的数据 } } class CommonViewController: UIViewController { var sceneType: CommonSceneType! // 所有逻辑根据sceneType取对应数据即可 }
内容的提问来源于stack exchange,提问作者TeddyKen
相关产品推荐
相关产品推荐

