Reputation: 2550
Here is the code
view.addObserver(self, forKeyPath: "center", options: .New, context: nil)
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
guard let change = change else {
return
}
print(change)
guard let newCenter = change["new"] else {
return
}
print(newCenter.dynamicType)
}
And the output is :
["new": NSPoint: {50, 50.5}, "kind": 1]
NSConcreteValue
I don't know why NS class will appear in iOS. How to correctly observe view.center/frame/transform using KVO with swift?
Upvotes: 0
Views: 960
Reputation: 385840
Since KVO is part of the Objective-C runtime, the change dictionary is an NSDictionary
, not a native Swift dictionary. An NSDictionary
can only hold Objective-C objects (which is why, in Swift, it becomes a [String:AnyObject]
, not a [String:Any]
), and CGPoint
is not an Objective-C object. So KVO has to wrap the CGPoint
in an object.
NSValue
is a generic Objective-C class for wrapping non-objects, and KVO uses it when the observed property's type is not an object type. NSValue
is a “class cluster”, which means it defines an interface and may have specialized, non-public subclasses that implement the interface. In this case, you're seeing the name of one of those subclasses: NSConcreteValue
.
You can get the CGPoint
value from the NSValue
by asking for its CGPointValue
property:
guard let newCenter = change["new"]?.CGPointValue else {
return
}
The reason you see NSPoint
when you print the change dictionary is an accident of history. The NSPoint
type is older than CGPoint
, but is now an alias for CGPoint
on OS X (defined in Foundation/NSGeometry.h
), and doesn't exist at all on iOS. However, the code to print NSPoint
/CGPoint
was not changed to use the new name (probably for backward compatibility) and the same code is used on both OS X and iOS.
Upvotes: 3