我偶然发现了Xcode 6中的键值编码问题。似乎不可能在id符合协议的情况下使用键值编码。
当属性声明为id时,编译器同意
@property (nonatomic, strong) id foo;
[foo setValue:@"value" forKey:@"key"];
当我设置id以符合协议时,我得到编译器错误。 “没有已知的选择器实例方法......”。
@property (nonatomic, strong) id<MyProtocol> foo;
[foo setValue:@"value" forKey:@"key"];
如果我将类型设置为NSObject,它会起作用,如下所示:
@property (nonatomic, strong) NSObject<MyProtocol> *foo;
[foo setValue:@"value" forKey:@"key"];
协议“MyProtocol”符合NSObject,但据我所知,该对象必须是NSObject的子类才能使KVC正常工作。但为什么第一种情况有效而不是第二种?
答案 0 :(得分:3)
这在Xcode 6中并不新鲜。(我刚刚测试了Xcode 5.1.1并收到错误。)规则如下:
编译器允许您向裸id
发送任何消息。
如果消息是由其中一个命名协议定义的,编译器只允许您向id<Protocol1, Protocol2, Protocol3, ...>
发送消息。
如果消息由类中的某个命名协议或定义,编译器将只允许您向SomeClass<Protocol1, Protocol2, Protocol3, ...>
发送消息。该类定义的消息包括由其超类及其类别定义的消息。
setValue:forKey:
方法在NSKeyValueCoding
category的NSObject
class中定义。它未在NSObject
protocol上定义。