bbu*_*bum 234
void * 表示"对带有无类型/未知内容的某些随机块内存的引用"
id 表示"对未知类的一些随机Objective-C对象的引用"
还有其他语义差异:
在GC Only或GC Supported模式下,编译器将为类型的引用发出写屏障id,但不会为类型发出写屏障void *.在声明结构时,这可能是一个关键的区别.void *_superPrivateDoNotTouch;如果_superPrivateDoNotTouch实际上是一个对象,声明iVars 会导致过早收获对象.不要那样做.
尝试在void *类型引用上调用方法将禁止编译器警告.
尝试调用id类型上的方法只会警告所调用的方法是否尚未@interface在编译器看到的任何声明中声明.
因此,永远不应该将对象称为void *.类似地,应该避免使用id类型变量来引用对象.尽可能使用最具体的类类型引用.甚至NSObject *比id因为编译器至少可以提供针对该引用的方法调用的更好验证更好.
一个常见且有效的用途void *是作为通过其他API传递的不透明数据引用.
考虑以下sortedArrayUsingFunction: context:方法NSArray:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
Run Code Online (Sandbox Code Playgroud)
排序函数将声明为:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,NSArray只是将传入的任何内容作为context参数传递给方法作为context参数.就NSArray而言,它是一个不透明的指针大小数据块,你可以随意使用它来实现你想要的任何目的.
如果没有语言中的闭包类型功能,这是使用函数携带大量数据的唯一方法.例; 如果你希望mySortFunc()有条件地排序为区分大小写或不区分大小写,同时仍然是线程安全的,你将在上下文中传递is-case敏感指示符,可能是在进入和离开的方式.
易碎且容易出错,但唯一的方法.
块解决了这个问题 - 块是C的闭包.它们在Clang中可用 - http://llvm.org/并且在Snow Leopard中很普遍(http://developer.apple.com/library/ios/documentation/Performance /Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).
Pet*_*wis 19
id是指向目标C对象的指针,其中void*是指向任何东西的指针.
id还会关闭与调用未知方法相关的警告,例如:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
不会给出关于未知方法的通常警告.当然,它会在运行时引发异常,除非obj为nil或者确实实现了该方法.
通常你应该使用NSObject*或id<NSObject>优先使用id,至少确认返回的对象是Cocoa对象,这样你就可以安全地使用retain/release/autorelease等方法.
如果方法具有返回类型,则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.