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?
Best Answer
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 withString?
, that type is toll-free bridged toNSString
, so it is semantically equivalent toNSString *
, an Objective-C type that the runtime knows full-well how to deal with. But compare that toInt?
whose semantic equivalent would beOptional<Int>
, notUnsafePointer<Int>
orNSNumber *
like you might expect. For now, you'll need to convince the typechecker that it is safe to represent in Objective-C by usingNSNumber!
.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.