Objective C中的id和NSObject有什么不同?

时间:2010-05-23 10:48:57

标签: objective-c

这有什么不同:

ID:

#import <objc/Object.h>

@interface Forwarder : Object
{
    id something;
}

NSObject的:

#import <objc/Object.h>

@interface Forwarder : Object
{
    NSObject *something;
}

Thz u。

3 个答案:

答案 0 :(得分:16)

来自This Greg MILLER's blog post

unixjunkie blog总结了差异

一些摘录:

  

对于Objective-C中以下三个声明之间的区别,经常会产生混淆:

id foo1;
NSObject *foo2;
id<NSObject> foo3;
  
      
  • 第一个是最常见的   它只是声明一个指向某个Objective-C对象的指针(参见/usr/include/objc/objc.h)。 id为编译器提供了有关对象实际类型的信息,因此编译器无法为您进行编译时类型检查。

  •   
  • 仅仅因为我们知道id是Objective-C对象并不意味着它指向一个派生自NSObject的对象,或者它甚至具有常见的方法,如retain和release。登记/>   一种解决方案是使用NSObject*静态输入变量,如上面的数字2所示   这为编译器提供了有关foo2指向的对象类的信息,因此编译器可以发出警告,如果您向foo2发送NSObject没有响应的消息。这意味着您可以安全地调用保留,释放,描述等,但如果您调用长度或计数或NSObject没有响应的任何内容,编译器将发出警告。

  •   
  • 将对象声明为id<NSObject>告诉编译器您不关心对象的类型,但您确实知道它符合指定的NSObject协议{{1} }。
       **名为**的协议(@protocol)。还有一个名为NSObject的类确实符合NSObject协议,但它们是两个不同的东西
      编译器将确保您分配给该指针的所有对象都符合所需的协议   像这样输入的指针可以安全地保存任何NSObject(因为NSObject符合NSObject协议),但它也可以包含任何NSObject,因为NSProxy也符合NSObject协议。
      在英语中,声明NSProxy foo3;说“foo3是一个指向任何类型的对象的指针,其行为类似于NSObject”   这是非常强大,方便和富有表现力的。实际上,我们通常不关心对象是什么类型,我们只关心它响应我们想要发送它的消息(例如,保留,释放)。

  •   

  

如果您不想(或不能)进行任何类型检查,请使用普通ID。对于不知道它们返回的对象类型的方法的返回类型(例如,+ alloc),这是很常见的。将委托声明为类型id也很常见,因为委托通常在运行时使用respondsToSelector:进行检查,并且通常不会保留委托。

     

但是,如果您确实需要编译时类型检查,则必须在第二种和第三种情况之间做出决定。好吧,让我帮助你 - 你想要第三种情况! :-)我非常,非常非常罕见地看到NSObject *工作的情况但是id不会。使用协议形式的优点是它可以与NSProxys一起使用。

答案 1 :(得分:3)

实际差异在于您不需要对id进行类型转换,但在使用之前通常需要对NSObject *进行类型转换。 NSObject是基类,几乎所有其他类都派生自id更多的语言关键字。

答案 2 :(得分:1)

id在没有编译器警告的情况下响应任何方法; NSObject只会在没有警告的情况下响应NSObject中定义的方法,包括NSObject协议。