如何扩展Bindable类以支持将键路径值绑定到函数?
解决Bindable类绑定到自定义函数的泛型错误问题
首先咱们先拆解你遇到的两个错误根源:
- Generic parameter 'O' is not used in function signature:你在扩展方法里声明了泛型参数
O,但整个函数的签名和实现里完全没用到这个类型,编译器会判定这是多余的无效声明,所以抛出错误。 - Generic parameter 'O' could not be inferred:因为
O没有在任何地方被实际使用,编译器根本没法推断出它的具体类型,自然会报这个错。
你的需求是实现类似RxSwift的bind(onNext:)——把Bindable的值变化传递给自定义闭包,这个场景根本不需要关联某个对象类型O,咱们直接去掉这个多余的泛型参数就能解决问题。
先看你的现有Bindable类(假设结构类似这样)
class Bindable<Value> { private var _value: Value private var observers: [(Value) -> Void] = [] var value: Value { get { _value } set { _value = newValue observers.forEach { $0(newValue) } } } init(value: Value) { self._value = value } // 你已有的绑定到UI元素的方法 func bind<O: AnyObject>(to object: O, _ objectKeyPath: ReferenceWritableKeyPath<O, Value>) { // 初始赋值 object[keyPath: objectKeyPath] = value // 添加观察者,值变化时更新UI元素 observers.append { [weak object] newValue in object?[keyPath: objectKeyPath] = newValue } } }
正确的扩展方法(实现bind(onNext:))
extension Bindable { func bind(onNext: @escaping (Value) -> Void) { // 先触发一次当前值,避免初始值没传递给闭包 onNext(value) // 添加观察者,值变化时调用自定义闭包 observers.append(onNext) } }
使用示例
// 定义测试用的User模型 struct User { var name: String } // 创建Bindable实例 let bindableUser = Bindable(value: User(name: "Harry Blue")) // 绑定到自定义闭包 bindableUser.bind { user in print("当前用户名:\(user.name)") } // 修改值,闭包会被自动触发 bindableUser.value.name = "Updated Name"
额外优化(可选:支持绑定属性KeyPath)
如果希望只监听Bindable值的某个属性(比如只关注User的name字段),可以再扩展一个带KeyPath的版本:
extension Bindable { func bind<Property>(_ keyPath: KeyPath<Value, Property>, onNext: @escaping (Property) -> Void) { // 初始传递当前属性值 onNext(value[keyPath: keyPath]) // 添加观察者,值变化时提取属性并传递给闭包 observers.append { newValue in onNext(newValue[keyPath: keyPath]) } } } // 使用示例 bindableUser.bind(\.name) { name in print("当前用户名:\(name)") }
这样就完全解决了泛型参数的问题,同时实现了你想要的绑定到自定义函数的功能~
内容的提问来源于stack exchange,提问作者Harry Blue
相关产品推荐
相关产品推荐

