I'm successfully using the setValue(value, forKey: key)
method in my NSKeyValueCoding compliant Swift NSObject subclass.
This works perfectly well on String optionals, e.g.
var name:String?
However, on Int optionals, it fails, triggering the undefined key method that I have overridden for debugging purposes:
override func setValue(value: AnyObject!, forUndefinedKey key: String!) {
println("\(self) this class is not key value coding-compliant for the key \(key)")
}
So for example, a key of myId
with a good integer value would trigger the undefined key method above.
var myId:Int?
If I change the above definition to be non-optional, then everything works fine:
var myId:Int = 0
With myId
as an optional, I have tried absolutely everything I can think of in the way of casting, unwrapping, initialising, and so on. It just doesn't see the class as key value compliant for those numeric values.
I know that it is a good numeric value. Changing the var declaration to String? crashes. It also looks fine in lldb:
Printing description of key:
myId
key NSObject 0x00007fb8d530ca20 0x00007fb8d530ca20
k NSString "myId" 0x00007fa2aa942f20
value __NSCFNumber * Int64(4348129) 0xb000000004258e13
Printing description of value:
4348129
(lldb)
So, the question is, has anyone used - in Swift - the NSKeyValueCoding method setValue(value, forKey: key)
on an Int type successfully?
KVO cannot function with pure Swift optionals because pure Swift optionals are not Objective-C objects. Swift forbids the use of dynamic
or @objc
with generic classes and structures because there is no valid Objective-C equivalent, and so the runtime is not setup to support KVO on instances of those kinds of objects. As for why it works with String?
, that type is toll-free bridged to NSString
, so it is semantically equivalent to NSString *
, an Objective-C type that the runtime knows full-well how to deal with. But compare that to Int?
whose semantic equivalent would be Optional<Int>
, not UnsafePointer<Int>
or NSNumber *
like you might expect. For now, you'll need to convince the typechecker that it is safe to represent in Objective-C by using NSNumber!
.
This is completely backwards and, in my opinion, an unfortunate limitation of the type system. For any engineers that come across this post, see rdar://18624182.
If you're willing to ditch Swift types change:
var myId:Int?
to:
var myId:NSNumber?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With