Combine框架中KVO Publisher属性变更时未发送信号的问题咨询
问题分析与修复方案
你遇到的问题其实是Combine KVO Publisher的常见坑——Swift属性默认不支持KVO的动态监听,除非你明确告诉编译器要为它启用运行时的动态派发支持。
问题根源
你的SampleClass里的name属性只加了@objc,但缺少dynamic修饰符。Combine的KVO Publisher底层依赖Objective-C的KVO机制,而KVO要求属性的setter方法能被运行时动态替换(isa-swizzling),Swift的@objc属性默认是静态派发的,所以当你修改a.name时,并不会触发KVO通知,自然Combine的Publisher也就不会发送新值事件。
修复代码
只需要给name属性加上dynamic修饰即可:
@objc class SampleClass: NSObject { @objc dynamic var name: NSString = "1" // 这里加上dynamic } var a = SampleClass() let kvoPublisher = a.publisher(for: \.name) .sink(receiveCompletion: { print("completion \($0)") }, receiveValue: { newVal in print("new val - \(newVal)") }) a.name = "2" a.name = "3" print("Finished; publisher = \(kvoPublisher) | a.name = \(a.name)")
修复后的输出
运行修改后的代码,控制台会输出:
new val - 1 new val - 2 new val - 3 Finished; publisher = Combine.AnyCancellable | a.name = 3
额外注意点
另外提一句:你的kvoPublisher(AnyCancellable)被赋值给了顶层变量,这保证了它不会被提前释放,所以能持续接收事件。如果是在函数内部创建的AnyCancellable,记得要把它存入一个Set<AnyCancellable>或者保持引用,否则会被销毁,导致Publisher停止工作。
内容的提问来源于stack exchange,提问作者nrx
相关产品推荐
相关产品推荐

