如何基于Swift为所有UIViewController实现通用功能?
为所有UIViewController实现通用标准化行为的Swift方案
嘿,针对你要给100个UIViewController统一添加标准化行为的需求,我整理了几个Swift里非常实用的方案,每个都有自己的适用场景,你可以按需挑选:
1. 子类继承方案(最直接的常规做法)
这是最容易理解和维护的方案,适合所有ViewController都需要这个通用行为的场景:
首先创建一个基础ViewController类,把通用逻辑集成进去:
class MyBaseClass { public func load(viewController: UIViewController){ print("The size of the view is \(viewController.view.frame.size.width)") } } class BaseViewController: UIViewController { private let baseBehavior = MyBaseClass() override func viewDidLoad() { super.viewDidLoad() // 在基础类中统一调用通用行为 baseBehavior.load(viewController: self) } }
然后让你现有的100个ViewController都继承这个BaseViewController:
// 示例业务ViewController class HomeViewController: BaseViewController { override func viewDidLoad() { super.viewDidLoad() // 这里添加你的业务逻辑,通用行为已经自动执行了 } }
优缺点:
- ✅ 实现简单,逻辑集中,后续修改通用行为只需要改Base类
- ❌ 如果已有部分ViewController继承了其他自定义父类,需要调整继承链,灵活性稍弱
2. 扩展+方法交换(无侵入式全局添加)
如果你不想修改现有ViewController的继承关系,可以用Swift的Extension结合Method Swizzling来实现无侵入的全局行为注入:
class MyBaseClass { public func load(viewController: UIViewController){ print("The size of the view is \(viewController.view.frame.size.width)") } } extension UIViewController { // 静态方法用于触发方法交换 static let swizzleViewDidLoad: Void = { let originalSelector = #selector(viewDidLoad) let swizzledSelector = #selector(swizzled_viewDidLoad) guard let originalMethod = class_getInstanceMethod(self, originalSelector), let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) else { return } // 交换viewDidLoad的实现 method_exchangeImplementations(originalMethod, swizzledMethod) }() @objc private func swizzled_viewDidLoad() { // 先调用原有的viewDidLoad逻辑 self.swizzled_viewDidLoad() // 执行通用行为 let baseBehavior = MyBaseClass() baseBehavior.load(viewController: self) } }
然后在App启动时触发方法交换(比如AppDelegate或者SceneDelegate):
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 触发交换,让所有UIViewController都自动执行通用行为 UIViewController.swizzleViewDidLoad return true }
优缺点:
- ✅ 完全不修改现有ViewController的代码,侵入性极低
- ❌ 方法交换属于黑魔法,使用不当容易引发难以排查的bug(比如多个地方交换同一个方法),建议只在全局统一行为的场景下谨慎使用
3. 协议+扩展(灵活的选择性添加)
如果不是所有ViewController都需要这个行为,或者你想遵循Swift的协议导向编程(POP),可以用协议+扩展的方式:
class MyBaseClass { public func load(viewController: UIViewController){ print("The size of the view is \(viewController.view.frame.size.width)") } } // 定义协议 protocol StandardBehaviorEnabled { func setupStandardBehavior() } // 给协议添加默认实现,限定只有UIViewController遵守时才生效 extension StandardBehaviorEnabled where Self: UIViewController { func setupStandardBehavior() { let baseBehavior = MyBaseClass() baseBehavior.load(viewController: self) } }
然后让需要这个行为的ViewController遵守协议并调用方法:
class SettingsViewController: UIViewController, StandardBehaviorEnabled { override func viewDidLoad() { super.viewDidLoad() // 调用通用行为 self.setupStandardBehavior() } }
优缺点:
- ✅ 灵活性极高,可以选择性给ViewController添加行为,符合Swift的设计理念
- ❌ 如果需要给100个VC都添加,还是需要逐个让它们遵守协议(不过可以结合方法交换优化,自动给所有VC添加,但复杂度会上升)
方案选择建议
- 如果所有100个VC都必须拥有这个行为:优先选择子类继承方案,维护成本最低;如果不想修改继承链,再考虑扩展+方法交换(注意安全)
- 如果只是部分VC需要:选择协议+扩展的方案,更灵活可控
内容的提问来源于stack exchange,提问作者Benjamin RD
相关产品推荐
相关产品推荐

