Objective-C:id和void之间的区别*
id
和void *
什么区别?
void *
表示“对某些随机块或者无types/未知内容的引用”
id
意思是“对某个未知类的随机Objective-C对象的引用”
还有其他的语义差异:
-
在“仅GC”或“GC支持”模式下,编译器将为types
id
引用发出写入障碍,但不会为void *
types。 在声明结构时,这可能是一个关键的区别。 声明iVars像void *_superPrivateDoNotTouch;
如果_superPrivateDoNotTouch
实际上是一个对象,将导致对象过早收割。 不要这样做。 -
试图调用
void *
types的引用上的方法将禁止编译器警告。 -
试图调用
id
types的方法只会在被调用的方法没有在编译器看到的任何@interface
声明中声明时才会发出警告。
因此,不应该把一个对象称为void *
。 同样,应该避免使用一个id
types的variables来引用一个对象。 使用最具体的类types的引用,你可以。 即使NSObject *
比id
好,因为编译器至less可以更好地validation对该引用的方法调用。
void *
的一个普通和有效的用法是作为一个不透明的数据引用,通过其他一些API传递。
考虑NSArray
的sortedArrayUsingFunction: context:
方法:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
sortingfunction将被声明为:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
在这种情况下,NSArray只是将作为context
参数传入的任何东西作为context
parameter passing给方法。 就NSArray而言,它是一个不透明的指针大小的数据块,你可以自由地将它用于任何你想要的目的。
如果没有语言中的闭包types特征,这是通过函数携带大量数据的唯一方法。 例; 如果您希望mySortFunc()有条件地按照区分大小写或不区分大小写的方式进行sorting,而且仍然是线程安全的,则可以在上下文中传递区分大小写的指示符,可能会在进出的路上投射。
脆弱和容易出错,但只有这样。
块解决这个问题 – 块是closuresC.它们可以在铛 – http://llvm.org/和普遍在雪豹(; http://developer.apple.com/library/ios/documentation/Performance /Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf )。
id是一个指向客观C对象的指针,其中void *是指向任何东西的指针。
ID也会closures与调用未知方法有关的警告,例如:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
不会给未知的方法通常的警告。 当然,除非obj没有,或者确实实现了这个方法,否则它会在运行时抛出exception。
通常你应该使用NSObject*
或id<NSObject>
优先于id
,它至less证实返回的对象是一个Cocoa对象,所以你可以放心地使用像retain / release / autorelease这样的方法。
如果一个方法有返回types的id
你可以返回任何Objective-C对象。
void
手段,该方法不会返回任何东西。
void *
只是一个指针。 您将无法编辑指针指向的地址上的内容。
id
是一个指向Objective-C对象的指针。 void *
是一个指向任何东西的指针。 你可以使用void *
而不是id
,但是不推荐使用,因为你永远不会得到编译器的警告。
你可能想看到stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject和unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs -id.html 。
/// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }; /// A pointer to an instance of a class. typedef struct objc_object *id;
上面的代码来自objc.h,所以看起来像id是objc_object结构的一个实例,并且isa指针可以与任何Objective C Class对象绑定,而void *只是一个无types的指针。
我的理解是,id代表一个指向对象的指针,而void *可以指向任何东西,只要你把它转换为你想要使用的types
除了已经说过的之外,与集合相关的对象和指针还是有区别的。 例如,如果你想把东西放到NSArray中,你需要一个对象(types为“id”),并且你不能在那里使用一个原始数据指针(types为“void *”)。 您可以使用[NSValue valueWithPointer:rawData]
将void *rawDdata
转换为“id”types以在集合中使用它。 一般而言,“id”更加灵活,并且与附加的对象相关的语义更多。 这里有更多的例子解释Objective C的idtypes 。