2009-01-21 66 views

回答

51

使用变量类型id,您可以发送任何已知消息并且编译器不会发出抱怨。使用变量NSObject *,您只能发送由NSObject声明的消息(不是任何子类的方法),否则它将生成警告。一般来说,id是你想要的。

进一步说明:所有物体基本上都是id型。声明一个静态类型的意义是告诉编译器,“假设这个对象是这个类的成员。”所以如果你给它发送一个类没有声明的消息,编译器会告诉你,“等等,那个对象不应该得到那个消息!”另外,如果两个类具有名称相同但签名不同的方法(即参数或返回类型),则它可以猜测您为变量声明的类所指的方法。如果它被声明为id,编译器就会举起手来告诉你:“好的,我没有足够的信息,我随机选择了一个方法签名。” (这通常不会被通过声明NSObject*帮助,虽然,通常的冲突是两个具体的类之间。)

+2

很好的解释,尽管我毫不犹豫地说,“一般来说,id是你想要的”。虽然“id”由于动态类型而非常灵活,但它也不提供任何警告,因此如果调用不支持的方法,那么在编译时可能发生的问题将成为运行时问题。静态类型(使用MyClassName *等)明智地使用可以使生活变得更简单,特别是在Xcode中进行调试时(它可以显示更智能的对象摘要)或使用拼写错误或不完整的选择器捕获方法调用。 – 2009-06-25 07:28:16

+0

我打算绘制的区别是在id和NSObject *之间,而不是一般的静态类型。你希望使用id而不是静态类型作为NSObject更常见。 – Chuck 2009-06-25 14:57:19

17

id指“一个对象”,NSObject *装置“的NSObject或其子类之一的实例”。 Objective-C中有些对象不是NSObject(目前在Cocoa中遇到的对象是NSProxy,ProtocolClass)。如果某些代码需要某个特定类的对象,那么声明可以帮助编译器检查您是否正确使用它。如果你真的可以采取“任何对象” - 例如你正在宣布一个委托,并将通过respondsToSelector:调用来测试所有的方法发送 - 你可以使用id

另一种方式来声明对象变量是如“id <NSObject>”,意思是“它实现任何对象NSObject协议。

10

从我有限Objective-C的,不是所有的目标都从NSObject的衍生的理解(不像Java的所有的对象都派生自object),理论上可以有其他的根对象。ID可以适用于任何那些非NSObject的派生的对象的。

0

我想补充的另一个区别。当你添加一个协议id,它不再意味着它将是NSObject *类型,它只是意味着它将是任何分类这证实了该协议。

因此,举例来说,该代码不会抛出任何错误,因为NSObject的类别NSDelayedPerforming有一个方法:

id testId; 
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5]; 

然而,该代码会显示错误No known instance method for selector "performSelector:withObject:afterDelay:"

id<NSMutableCopying> testId; 
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5]; 
相关问题