Is key-value observation (KVO) available in Swift?
(Edited to add new info): consider whether using the Combine framework can help you accomplish what you wanted, rather than using KVO
Yes and no. KVO works on NSObject subclasses much as it always has. It does not work for classes that don't subclass NSObject. Swift does not (currently at least) have its own native observation system.
(See comments for how to expose other properties as ObjC so KVO works on them)
See the Apple Documentation for a full example.
swift - new Key-Value Observing (KVO) called only for .initial and not .new
As documented here you need to add dynamic
keyword to your variable declaration.
KVO Swift: newValue is always nil
You need to supply the new
option to the options
input argument of the observer
method to receive the new value in change
.
obs = observe(\.buggyApple, options: [.new], changeHandler: { (obj, change) in
print(change)
})
Key-Value-Observing closure never called on Boolean property
You can only use key-value observing with classes that inherit from
NSObject
.
means it's required that only objects in a subclass of NSObject
can be observed.
It does not mean that any object in a subclass of NSObject
is implicitly observable.
It seems that this property of NSToolbar
is not KVO compliant.
Key-Value Observing in Swift 4
I think the reason change
is coming up with nil
is because you haven't specified options.
Rewrite as follows:
override func viewDidLoad() {
super.viewDidLoad()
// configure the observation
token = self.observe(\.dishes, options: [.new,.old]) { object, change in
print(object)
let set1 = Set(change.newArray!)
let set2 = Set(change.oldArray!)
let filter = Array(set1.subtract(set2))
print(filter)
}
updateTableView()
}
Note that I have done a bit of guesswork here about your Dish
object. I am assuming you have made it conform to the Equatable
protocol, and this is a necessary step for the solution to work.
UPDATE: This requirement has now been reflected in the official Apple documentation here.
If you don't need to know how a property has changed, omit the options parameter. Omitting the options parameter forgoes storing the new and old property values, which causes the oldValue and newValue properties to be nil.
How to remove an KVO observer added with observe() API?
Example of using key-value observing
/// define an Observer
var observation: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
/// start observation
observation = view.observe(\.backgroundColor, options: [.old, .new], changeHandler: { (view, value) in
})
/// invalidate observation
observation?.invalidate()
observation = nil
}
Swift KVO on an object conforming to a protocol
Make sure to mark the observed property as @objc
and dynamic
. As Using Key-Value Observing in Swift says:
Mark properties that you want to observe through key-value observing with both the
@objc
attribute and thedynamic
modifier.
The protocol and participating classes will need to be marked @objc
, too. E.g.:
class MyCustomClass: NSObject { ... }
@objc protocol X: NSObjectProtocol {
@objc dynamic var toBeObserved: MyCustomClass? { get }
}
class A: NSObject, X {
var toBeObserved: MyCustomClass? = MyCustomClass()
}
class B: NSObject {
@objc var x: X = A()
var token: NSKeyValueObservation?
func addObserver() {
token = observe(\.x.toBeObserved) { object, _ in
print(object)
}
}
}
Related Topics
How to Make a Swiftui List Scroll Automatically
How to Use Special Character in Nsurl
Non-'@Objc' Method Does Not Satisfy Optional Requirement of '@Objc' Protocol
Swift 2 ( Executefetchrequest ): Error Handling
Using a Type Variable in a Generic
How Change Background Color If Using Navigationview in Swiftui
Firebase Getting Data in Order
How to Convert a Base64String to String in Swift
Convert String to Date in Swift
String Value to Unsafepointer≪Uint8≫ Function Parameter Behavior
Dynamically Hiding View in Swiftui
Forced to Cast, Even If Protocol Requires Given Type
Instance Member Cannot Be Used on Type