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

如何为同基类的不同类共享Swift协议扩展实现?

解决方法

方法一:使用Block式通知注册(推荐,彻底规避Selector冲突)

直接采用NotificationCenter的block注册API,绕开Objective-C Runtime和Selector的限制,完美适配Swift协议扩展的场景:

protocol MyListener {
    func setupMyViewControllers()
    func receiveUpdateA(_ notification: Notification)
    func receiveUpdateB(_ notification: Notification)
}

// 协议扩展共享setup逻辑
extension MyListener where Self: UIViewController {
    func setupMyViewControllers() {
        // 用block注册通知,无需依赖Selector
        NotificationCenter.default.addObserver(forName: NSNotification.Name("receiveUpdateA"), object: nil, queue: .main) { [weak self] notification in
            self?.receiveUpdateA(notification)
        }
        
        NotificationCenter.default.addObserver(forName: NSNotification.Name("receiveUpdateB"), object: nil, queue: .main) { [weak self] notification in
            self?.receiveUpdateB(notification)
        }
    }
}

// 仅需让需要的ViewController遵守协议并实现接收方法
extension A: MyListener {
    func receiveUpdateA(_ notification: Notification) {
        // 自定义业务逻辑
    }
    
    func receiveUpdateB(_ notification: Notification) {
        // 自定义业务逻辑
    }
}

extension B: MyListener {
    func receiveUpdateA(_ notification: Notification) {
        // 自定义业务逻辑
    }
    
    func receiveUpdateB(_ notification: Notification) {
        // 自定义业务逻辑
    }
}

这种方式不需要处理任何Objective-C暴露的配置,同时通过[weak self]避免了循环引用,只针对需要的ViewController共享setup代码。

方法二:保留Selector方式(适配Objective-C要求)

如果必须使用Selector注册通知,需要调整协议和方法声明,确保接收方法能被Objective-C识别:

// 协议本身不标记@objc,但强制接收方法为@objc
protocol MyListener {
    func setupMyViewControllers()
    @objc func receiveUpdateA(_ notification: Notification)
    @objc func receiveUpdateB(_ notification: Notification)
}

extension MyListener where Self: UIViewController {
    func setupMyViewControllers() {
        NotificationCenter.default.addObserver(self, selector: #selector(receiveUpdateA(_:)), name: NSNotification.Name("receiveUpdateA"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(receiveUpdateB(_:)), name: NSNotification.Name("receiveUpdateB"), object: nil)
    }
}

// 遵守协议的类必须用@objc修饰接收方法
extension A: MyListener {
    @objc func receiveUpdateA(_ notification: Notification) {
        // 自定义业务逻辑
    }
    
    @objc func receiveUpdateB(_ notification: Notification) {
        // 自定义业务逻辑
    }
}

extension B: MyListener {
    @objc func receiveUpdateA(_ notification: Notification) {
        // 自定义业务逻辑
    }
    
    @objc func receiveUpdateB(_ notification: Notification) {
        // 自定义业务逻辑
    }
}

关键注意事项:

  • 修正了方法签名:接收通知的方法必须携带Notification参数,与Selector的receiveUpdateA(_:)匹配(原代码中无参方法和Selector不对应,是隐藏的逻辑错误)。
  • 协议仅对接收方法标记@objc,避免了协议扩展方法被强制要求Objective-C可见的冲突。
  • 仅让需要的ViewController遵守MyListener协议,无需全局约束所有UIViewController。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:40:25