Is Key-Value Observation (Kvo) Available in Swift

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 the dynamic 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



Leave a reply



Submit