iOS Framework中Storyboard视图控制器如何引用App Bundle子类?
解决Framework Storyboard视图控制器使用App子类的问题
我明白你的需求:Framework里的Storyboard绑定了BaseViewController,但你想在集成这个Framework的App里,让这个Storyboard的控制器实例化为App中定义的MyInheritedViewController(继承自BaseViewController)。下面是几种可行的方案,按优雅程度排序:
方案一:Framework封装动态实例化方法(推荐)
这种方式最干净,Framework提供一个入口让App传入子类类型,内部通过NSCoder加载Storyboard布局并初始化子类:
在Framework的
BaseViewController中添加静态方法
确保BaseViewController的init(coder:)是open或public的(默认如果是open class,init(coder:)会继承为open),然后添加封装方法:open class BaseViewController: UIViewController { // 你的核心功能代码... /// 从Framework的Storyboard实例化指定子类的控制器 /// - Parameter type: 继承自BaseViewController的子类类型 /// - Returns: 子类实例,带有Storyboard中的布局 public static func instantiateSubclass<T: BaseViewController>(_ type: T.Type) -> T? { let frameworkBundle = Bundle(for: self) let storyboard = UIStoryboard(name: "你的Framework Storyboard名称", bundle: frameworkBundle) // 获取Storyboard中控制器的coder(这里以初始控制器为例,也可以用identifier) guard let baseCoder = storyboard.instantiateInitialViewController()?.coder else { assertionFailure("无法从Framework Storyboard获取coder") return nil } // 用coder初始化子类 return T(coder: baseCoder) } }在App中调用并使用子类
先定义你的子类:class MyInheritedViewController: BaseViewController { // 你的扩展功能,比如重写方法、添加新属性等 override func viewDidLoad() { super.viewDidLoad() // 自定义逻辑 } }然后通过Framework提供的方法实例化:
guard let customVC = BaseViewController.instantiateSubclass(MyInheritedViewController.self) else { return } // 现在customVC就是MyInheritedViewController的实例,带有Framework Storyboard的布局 navigationController?.pushViewController(customVC, animated: true)
方案二:App中直接通过Coder初始化子类
如果不想修改Framework代码,可以在App端直接处理:
// 获取Framework的Bundle let frameworkBundle = Bundle(for: BaseViewController.self) // 加载Framework的Storyboard let storyboard = UIStoryboard(name: "你的Framework Storyboard名称", bundle: frameworkBundle) // 获取原控制器的coder(如果是指定identifier的控制器,用instantiateViewController(withIdentifier:)) guard let baseCoder = storyboard.instantiateInitialViewController()?.coder else { fatalError("加载Framework Storyboard失败") } // 用coder初始化你的子类 let customVC = MyInheritedViewController(coder: baseCoder)! // 使用customVC
注意事项
- 确保
BaseViewController的init(coder:)没有被标记为private或fileprivate,否则子类无法调用。 - 如果Framework的Storyboard中控制器有自定义的
IBOutlet或IBAction,这些需要在BaseViewController中定义为open或public,这样子类才能访问或重写。 - 不要尝试直接修改Framework中Storyboard的控制器class(因为Framework是编译后的二进制,App无法修改其资源)。
内容的提问来源于stack exchange,提问作者Michał Ziobro
相关产品推荐
相关产品推荐

