如何为同基类的不同类共享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
相关产品推荐
相关产品推荐

