这有什么不同:
ID:
#import <objc/Object.h>
@interface Forwarder : Object
{
id something;
}
Run Code Online (Sandbox Code Playgroud)
NSObject的:
#import <objc/Object.h>
@interface Forwarder : Object
{
NSObject *something;
}
Run Code Online (Sandbox Code Playgroud)
你呢.
Von*_*onC 16
这篇来自unixjunkie博客的Greg MILLER博客文章 总结了这些差异
一些提取物:
关于Objective-C中以下三个声明之间的区别经常存在混淆:
id foo1;
NSObject *foo2;
id<NSObject> foo3;
Run Code Online (Sandbox Code Playgroud)
第一个是最常见的.
它只是声明一个指向某个Objective-C对象的指针(请参阅参考资料/usr/include/objc/objc.h).id为编译器提供了有关对象实际类型的信息,因此编译器无法为您进行编译时类型检查.仅仅因为我们知道id是Objective-C对象并不意味着它指向一个派生自的对象
NSObject,或者它甚至具有诸如retain和release之类的常用方法.
一种解决方案是静态输入我们的变量NSObject*,如上面的数字2所示.
这为编译器提供了有关foo2指向的对象类的信息,因此编译器可以发出警告,如果你向foo2发送一个NSObject没有响应的消息.这意味着您可以安全地调用保留,释放,描述等,但如果您调用长度或计数或任何NSObject不响应的内容,编译器将发出警告.声明一个对象
id<NSObject>告诉编译器您不关心该对象的类型,但您确实知道它符合指定的NSObject协议**.
**protocol(@protocol)命名NSObject.还有一个名为NSObject确实符合NSObject协议的类,但它们是两个不同的东西
编译器将确保您分配给该指针的所有对象符合所需的协议.
像这样输入的指针可以安全地保存任何指针NSObject(因为NSObject符合NSObject协议),但它也可以保存任何指针NSProxy,因为它NSProxy也符合NSObject协议.
在英语中,声明id<NSObject>foo3; 说"foo3是指向任何类型的对象的指针,其行为类似于NSObject".
这是非常强大,方便和富有表现力的.实际上,我们通常不关心对象是什么类型,我们只关心它响应我们想要发送它的消息(例如,保留,释放).
如果您不想(或不能)进行任何类型检查,请使用普通ID.对于不知道它们返回的对象类型的方法的返回类型(例如,+ alloc),这是很常见的.将委托声明为类型id也很常见,因为委托通常在运行时使用respondsToSelector:进行检查,并且通常不会保留委托.
但是,如果您确实需要编译时类型检查,则必须在第二种和第三种情况之间做出决定.好吧,让我帮助你 - 你想要第三种情况!:-)我非常,非常非常罕见地看到NSObject*工作的情况但是id不会.使用协议形式的优点是它可以与NSProxys一起使用.
| 归档时间: |
|
| 查看次数: |
3844 次 |
| 最近记录: |