这有什么不同:
ID:
#import <objc/Object.h>
@interface Forwarder : Object
{
id something;
}
NSObject的:
#import <objc/Object.h>
@interface Forwarder : Object
{
NSObject *something;
}
Thz u。
答案 0 :(得分:16)
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协议。