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

如何基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:54:46