如何使用RxSwift的DelegateProxy替代Protocol?
嘿,很高兴看到你在试着把RxSwift融入现有代码里!DelegateProxy确实是RxSwift适配传统Delegate模式的核心工具,咱们来聊聊这种转换的最优实现方式~
其实RxSwift官方已经有一套成熟的DelegateProxy模板,你参考的两篇文章方向是对的,只要你的代码符合以下步骤,基本就是最优方案:
1. 定义规范的DelegateProxy子类
首先要创建继承自DelegateProxy的子类,同时遵循DelegateProxyType和你的自定义Protocol,核心是把原生Delegate的get/set方法和Rx的代理体系绑定:
class YourCustomDelegateProxy: DelegateProxy<YourHostClass, YourCustomDelegate>, DelegateProxyType, YourCustomDelegate { // 关联宿主类的delegate属性 static func currentDelegate(for object: YourHostClass) -> YourCustomDelegate? { return object.delegate } static func setCurrentDelegate(_ delegate: YourCustomDelegate?, to object: YourHostClass) { object.delegate = delegate } // 注册代理到Rx的对象关联表,这步很关键 static func registerKnownImplementations() { self.register { YourCustomDelegateProxy(parentObject: $0, delegateProxy: self) } } }
这里要注意currentDelegate和setCurrentDelegate必须准确对应宿主类的delegate属性,registerKnownImplementations是Rx推荐的注册方式,能保证代理被正确绑定到宿主对象上。
2. 给宿主类添加Rx扩展,暴露Observable接口
接下来给你的宿主类(比如自定义UI控件、业务类)写Rx扩展,把Delegate方法转换成Observable序列,让调用方能用Rx的方式订阅事件:
extension Reactive where Base: YourHostClass { // 获取代理实例 var customDelegate: DelegateProxy<YourHostClass, YourCustomDelegate> { return YourCustomDelegateProxy.proxy(for: base) } // 把Delegate里的didCompleteTask方法转成Observable var didCompleteTask: Observable<String> { return customDelegate.methodInvoked(#selector(YourCustomDelegate.didCompleteTask(_:))) .map { $0[0] as! String } } }
如果是带返回值的Delegate方法(比如func shouldAllowAction() -> Bool),记得用forwardToDelegate配合methodInvoked,这样既能捕获事件,又不会影响原生Delegate的逻辑执行。
3. 保证线程安全
RxSwift的DelegateProxy默认线程安全,但如果你的Delegate方法涉及UI操作,建议在Observable里加上observe(on: MainScheduler.instance),避免UI线程报错。
如果你的代码满足以下几点,那就是非常标准的最优实现了:
- 不重复造轮子:完全复用RxSwift提供的
DelegateProxyType协议和工具方法,不用自己写繁琐的代理转发逻辑 - 接口简洁:宿主类的Rx扩展只暴露业务相关的Observable,不泄露内部代理细节
- 兼容性强:保留原生Delegate的能力,允许同时使用原生Delegate和Rx Observable(通过
forwardToDelegate) - 注册正确:调用了
registerKnownImplementations,确保代理能被Rx正确识别
- 别忘了在App初始化时调用
YourCustomDelegateProxy.registerKnownImplementations(),不然代理根本不会生效 - 如果你的Protocol是Swift原生的(没有@objc标记),要确保DelegateProxy能正确通过Runtime捕获方法调用,必要时给Protocol加上@objc
- 对于可选的Delegate方法,要确认
methodInvoked的selector完全匹配,避免找不到方法导致崩溃
总的来说,你参考的两篇文章方向没问题,只要遵循上面的标准范式,就是将Swift Protocol转换为RxDelegateProxy的最优方式啦~
内容的提问来源于stack exchange,提问作者Pangu

