That code won't work for two reasons:
You must add the dynamic
attribute to the area
property, as described in the section “Key-Value Observing” under “Adopting Cocoa Design Patterns” in Using Swift with Cocoa and Objective-C.
You must declare that area
depends on width
and height
as described in “Registering Dependent Keys” in the Key-Value Observing Programming Guide. (This applies to Objective-C and Swift.) And for this to work, you also have to add dynamic
to width
and height
.
(You could instead call willChangeValueForKey
and didChangeValueForKey
whenever width
or height
changes, but it's usually easier to just implement keyPathsForValuesAffectingArea
.)
Thus:
import Foundation
class MyObject: NSObject {
@objc dynamic var width: Double = 0
@objc dynamic var height: Double = 0
@objc dynamic private var area: Double {
return width * height
}
@objc class func keyPathsForValuesAffectingArea() -> Set<String> {
return [ "width", "height" ]
}
func register() {
self.addObserver(self, forKeyPath: "area", options: [ .old, .new ], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("observed \(keyPath) \(change)")
}
}
let object = MyObject()
object.register()
object.width = 20
object.height = 5
Output:
observed Optional("area") Optional([__C.NSKeyValueChangeKey(_rawValue: new): 0, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 0])
observed Optional("area") Optional([__C.NSKeyValueChangeKey(_rawValue: new): 100, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 0])
RxSwift
. – Mulloy