Swift Combine:为何sink适配model.$name却不支持model.name.publisher?
问题:@Published属性为何必须用
$name才能触发订阅,name.publisher无效? 我定义了一个带有@Published属性的ObservableObject模型:
@MainActor class MyModel:ObservableObject { @Published private(set) var name = "" .... }
我发现使用model.$name调用sink时可以正常触发回调,但使用model.name.publisher时却无法触发:
正常运行的代码:
model.$name .receive(on: RunLoop.main) .sink { name in .... // 可正常调用,运行正常 } .store(in: &subs)
无法触发回调的代码:
model.name.publisher .receive(on: RunLoop.main) .sink { name in .... // 无法调用 } .store(in: &subs)
请问为何必须在name前使用$符号,而name.publisher无法生效?
原因分析
$name是@Published自动生成的专用变化监听Publisher
当你给属性添加@Published包装器时,Swift会自动生成一个名为$属性名的投影属性,它是绑定到该属性的Published.Publisher实例。这个Publisher会在name的值发生修改时,自动把新值发送给所有订阅者,这也是@Published实现响应式更新的核心机制。name.publisher是通用一次性值Publisher,不监听后续变化name.publisher是Swift为所有类型提供的通用扩展方法,它只会一次性发送当前的name值,发送完成后就结束了,不会再追踪name的后续变更。它的作用只是把当前值转换成一个仅发送一次信号的Publisher,和@Published的响应式更新逻辑完全无关。
简单总结:$name是跟着@Published绑定的“实时变化追踪器”,而name.publisher只是“当前值的一次性发射器”,前者会响应属性的每一次修改,后者只会发一次当前值就终止,所以后者无法在name更新时触发回调。
内容的提问来源于stack exchange,提问作者zumzum
相关产品推荐
相关产品推荐

