Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

Objective-C: difference between id and void *

What is the difference between id and void *?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

void * means "a reference to some random chunk o' memory with untyped/unknown contents"

id means "a reference to some random Objective-C object of unknown class"

There are additional semantic differences:

  • Under GC Only or GC Supported modes, the compiler will emit write barriers for references of type id, but not for type void *. When declaring structures, this can be a critical difference. Declaring iVars like void *_superPrivateDoNotTouch; will cause premature reaping of objects if _superPrivateDoNotTouch is actually an object. Don't do that.

  • attempting to invoke a method on a reference of void * type will barf up a compiler warning.

  • attempting to invoke a method on an id type will only warn if the method being called has not been declared in any of the @interface declarations seen by the compiler.

Thus, one should never refer to an object as a void *. Similarly, one should avoid using an id typed variable to refer to an object. Use the most specific class typed reference you can. Even NSObject * is better than id because the compiler can, at the least, provide better validation of method invocations against that reference.

The one common and valid use of void * is as an opaque data reference that is passed through some other API.

Consider the sortedArrayUsingFunction: context: method of NSArray:

- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;

The sorting function would be declared as:

NSInteger mySortFunc(id left, id right, void *context) { ...; }

In this case, the NSArray merely passes whatever you pass in as the context argument to the method through as the context argument. It is an opaque hunk of pointer sized data, as far as NSArray is concerned, and you are free to use it for whatever purpose you want.

Without a closure type feature in the language, this is the only way to carry along a hunk of data with a function. Example; if you wanted mySortFunc() to conditionally sort as case sensitive or case insensitive, while also still being thread-safe, you would pass the is-case-sensitive indicator in the context, likely casting on the way in and way out.

Fragile and error prone, but the only way.

Blocks solve this -- Blocks are closures for C. They are available in Clang -- http://llvm.org/ and are pervasive in Snow Leopard (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...