为什么添加协议(到id)会导致语义问题?

时间:2013-12-29 20:56:10

标签: objective-c xcode

假设我有一个像这样的小课:

@interface ABPair : NSObject
@property id key;
@property id value;
- (void) printSize;
@end

@implementation ABPair
- (void) printSize {
    NSLog(@"the size of your key is: %@", NSStringFromSize([self.key sizeWithAttributes: nil]));
}
@end

编译时没有警告(在Xcode 5中),并且运行成功,并打印出合理的值。

然而,如果我做了这个改变:

@property id<NSCopying> key;

然后我得到两个编译器错误:

  • ARC语义问题:没有已知的选择器'sizeWithAttributes:'
  • 的实例方法
  • 语义问题:将'id'传递给不兼容类型'NSSize'的参数(又名'struct CGSize')

当我没有提供任何关于类型的信息时,为什么编译器能够识别正确的方法(在NSString上),但是当我说该对象必须是该类符合的协议时,无法识别该方法?

1 个答案:

答案 0 :(得分:3)

id key声明一个“通用”Objective-C变量。它可以指向任何物体, 并且编译器接受发送给它的任何消息。 如果使用ARC进行编译,则只需要知道消息签名 根本就是编译器(来自任何类)。

id<myprotocol> key专门声明指向符合该协议的对象的指针。 编译器仅接受来自<myprotocol>协议(或<myprotocol>继承的其他协议)的消息。