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

OOP继承与POP对比:iOS视图控制器IBOutlet及方法复用选型问题

场景选型与实现方案解答

1. 当前场景是否继承比协议更合适?

是,这个场景下继承是性价比更高的选择。
你们的两个ViewController完全符合is-a的继承适用条件:SecondViewController的UI组件(IBOutlet)、presenter依赖、基础业务逻辑完全是FirstViewController的超集,没有需要裁剪父类能力的场景。使用继承可以直接复用父类所有存储属性(包括IBOutlet、presenter实例)和成员方法,不需要重复声明任何公共代码,代码量最少,维护成本最低。
业界提倡优先使用POP是为了避免继承带来的强耦合、单继承限制等问题,不是要求所有场景硬套POP,匹配业务场景的方案才是最优的。

2. 选择协议方案如何避免重复代码?

你之前的协议方案问题在于Swift的协议本身不能定义存储属性,只能定义属性约束,所以IBOutlet这类存储属性无法直接在协议层复用,公共方法可以通过协议默认实现复用,完整实现步骤如下:

步骤1:抽取公共能力协议

声明公共的属性约束和方法要求,限定协议仅能被类遵守:

protocol CommonVCProtocol: AnyObject {
    // 公共IBOutlet约束
    var firstButton: UIButton! { get set }
    var secondButton: UIButton! { get set }
    // 公共presenter约束
    var presenter: CommonPresenterProtocol! { get set }
    // 公共业务方法要求
    func firstFunction()
    func secondFunction()
}

步骤2:添加协议默认实现

给协议添加扩展,约束实现者为UIViewController类型,就可以在默认实现里直接访问UIKit能力和协议声明的公共属性:

extension CommonVCProtocol where Self: UIViewController {
    func firstFunction() {
        // 公共逻辑直接写在这里,可直接调用firstButton、presenter等属性
        firstButton.isSelected = true
        presenter.loadCommonData()
    }
    
    func secondFunction() {
        // 公共逻辑实现
    }
}

步骤3:抽取新增功能的独立协议

protocol AdditionalVCProtocol: AnyObject {
    var additionalButton: UIButton! { get set }
    func additionalFunction()
}

extension AdditionalVCProtocol where Self: UIViewController {
    func additionalFunction() {
        // 新增逻辑实现
    }
}

步骤4:两个ViewController分别遵守协议

注意:存储属性(IBOutlet、presenter)还是需要在各自的类中单独声明,这是Swift语法的限制,无法通过协议规避

class FirstViewController: UIViewController, CommonVCProtocol {
    // 仍需单独声明公共IBOutlet
    @IBOutlet weak var firstButton: UIButton!
    @IBOutlet weak var secondButton: UIButton!
    var presenter: CommonPresenterProtocol!
    // 公共方法已经有默认实现,无需重复编写
}

class SecondViewController: UIViewController, CommonVCProtocol, AdditionalVCProtocol {
    // 仍需单独声明公共IBOutlet
    @IBOutlet weak var firstButton: UIButton!
    @IBOutlet weak var secondButton: UIButton!
    var presenter: CommonPresenterProtocol!
    // 新增IBOutlet
    @IBOutlet weak var additionalButton: UIButton!
    // 公共方法和新增方法都有默认实现,无需重复编写
}

3. 是否需要使用协议默认实现?

如果选择POP方案,必须用协议默认实现,否则两个ViewController都要重复编写所有公共业务方法,协议默认实现就是用来解决方法复用的核心手段。但存储属性的重复声明是Swift POP当前无法解决的问题。

最终选型建议

  • 如果后续两个ViewController不会出现功能分化(比如不需要裁剪FirstViewController的能力给SecondViewController用),直接选继承,代码更简洁。
  • 如果后续两个VC要分别叠加不同的横向能力(比如一个要支持分享、一个要支持草稿保存),或者会出现功能分化,选POP,灵活度更高,不会被单继承的继承树限制。

内容的提问来源于stack exchange,提问作者jackbob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:54:01