I've just started learning Combine and am quite confused with behaviour of KVO publishers. They just do not publish any events except for the initial value. Here is the sample code I used:
@objc class SampleClass: NSObject {
@objc var name: NSString = "1"
}
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)")
The console output is
new val - 1
Finished; publisher = Combine.AnyCancellable | a.name = 3
Could you please explain what am I missing here and how to fix it?
Thanks.
CodePudding user response:
You also need to mark the property as dynamic
in order for it to be KVO compliant. publisher(for:)
only works with KVO compliant properties, since it uses KVO under the hood.
@objc class SampleClass: NSObject {
@objc dynamic var name: NSString = "1"
}
Once you do that, the KVO publisher emits the updated values as expected.
For more information on @objc
vs @objc dynamic
, see this Q&A.
Bear in mind that you should only use KVO publishers when interacting with code that you cannot change. When you want to observe property values of types that you control, use @Published
instead.