如何正确为Eureka SelectableSection编写通用响应式扩展
错误原因
编译报错的核心原因是泛型约束的类型推断问题:SelectableSectionType 是Eureka定义的通用协议,遵守该协议的类型既可能是引用类型也可能是值类型。RxSwift的Reactive结构体中,base属性被定义为不可变的let常量:
- 当泛型约束为具体的
SelectableSection<ListCheckRow<Int>>类时,编译器明确知道base是引用类型,修改它的闭包属性只是修改实例的成员,不会改变base本身的指针,所以编译合法。 - 当泛型约束为
SelectableSectionType协议时,编译器无法确认遵守协议的是值类型还是引用类型,默认不允许修改let常量的属性,因此抛出错误。
解决方案
只需要在泛型约束中增加AnyObject限定,明确告诉编译器当前泛型对应的base一定是引用类型即可,修改后的通用扩展代码如下:
extension SelectableSection: ReactiveCompatible {} extension Reactive where Base: SelectableSectionType, Base: AnyObject { var selectedValue: Observable<Base.SelectableRow.Cell.Value?> { return Observable.create { observer in self.base.onSelectSelectableRow = { cell, row in observer.onNext(row.value) } return Disposables.create { observer.onCompleted() } } } }
注意事项
- Eureka中的
SelectableSection本身就是类类型,天然满足AnyObject约束,该扩展可以覆盖所有SelectableSection的使用场景,不需要针对不同的行值类型单独写扩展。 - 上述实现会直接覆盖
onSelectSelectableRow原有闭包,如果业务需要同时保留原有闭包的逻辑,可以通过关联对象存储原有闭包,在新闭包中先触发原有逻辑再发送响应式事件即可。
内容的提问来源于stack exchange,提问作者Radu
相关产品推荐
相关产品推荐

