问题
just wondering if this is possible in Swift 2.2, KVO on a computed property!?
ie:
var width = 0
var height = 0
private var area : Double {
get {
return with * height
}
}
self.addOberser(self, forKeyPath: "area", ......
Would a client code modifying the with or height trigger observeValueForKeyPath?
Just checking before engaging on a mayor class refactor. KVO's syntax being as annoying as it's is not worth even a playground if someone has an answer at hand (I am assuming answer is NO)
regards! ~d
回答1:
That code won't work for two reasons:
You must add the
dynamicattribute to theareaproperty, 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
areadepends onwidthandheightas 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 adddynamictowidthandheight.(You could instead call
willChangeValueForKeyanddidChangeValueForKeywheneverwidthorheightchanges, but it's usually easier to just implementkeyPathsForValuesAffectingArea.)
Thus:
class MyObject: NSObject {
dynamic var width: Double = 0
dynamic var height: Double = 0
dynamic private var area: Double {
return width * height
}
class func keyPathsForValuesAffectingArea() -> Set<String> {
return [ "width", "height" ]
}
func register() {
self.addObserver(self, forKeyPath: "area", options: [ .Old, .New ], context: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
print("observed \(keyPath) \(change)")
}
}
let object = MyObject()
object.register()
object.width = 20
object.height = 5
Output:
observed Optional("area") Optional(["old": 0, "new": 0, "kind": 1])
observed Optional("area") Optional(["old": 0, "new": 100, "kind": 1])
回答2:
As @Rob stated in his answer, make area dynamic to be observed from objective-c
Now add willSet { } and didSet { } for width and height properties,
inside willSet for both properties add this self.willChangeValueForKey("area")
and in didSet add self.didChangeValueForKey("area");
Now observers of area will be notified every time width or height change.
Note: this code is not tested, but I think it should do what expected
来源:https://stackoverflow.com/questions/36555492/kvo-on-swifts-computed-properties