Reputation: 6666
I have stumbled upon a problem with key value coding in Xcode 6. It seems as it's impossible to use key value coding on id's conforming to a protocol.
When a property is declared as id the compiler agrees
@property (nonatomic, strong) id foo;
[foo setValue:@"value" forKey:@"key"];
When I set the id to conform to a protocol I get a compiler error. "No known instance method for selector ...".
@property (nonatomic, strong) id<MyProtocol> foo;
[foo setValue:@"value" forKey:@"key"];
It works if I set the type to NSObject, like this:
@property (nonatomic, strong) NSObject<MyProtocol> *foo;
[foo setValue:@"value" forKey:@"key"];
The protocol "MyProtocol" conforms to NSObject, but as far as I understand the object is required to be a subclass of NSObject in order for KVC to work. But why does the first scenario work but not the second?
Upvotes: 1
Views: 347
Reputation: 385860
This isn't new in Xcode 6. (I just tested Xcode 5.1.1 and got an error.) The rules are:
The compiler will let you send any message to a bare id
.
The compiler will only let you send a message to id<Protocol1, Protocol2, Protocol3, ...>
if the message is defined by one of the named protocols.
The compiler will only let you send a message to SomeClass<Protocol1, Protocol2, Protocol3, ...>
if the message is defined by one of the named protocols, or by the class. Messages defined by the class include messages defined by its superclasses and its categories.
The setValue:forKey:
method is defined in the NSKeyValueCoding
category on the NSObject
class. It's not defined on the NSObject
protocol.
Upvotes: 3