views:

7212

answers:

3

In observeValueForKeyPath:ofObject:change:context: - why do the docs use NULL instead of nil when not specifying a context pointer?

+16  A: 

They're technically the same thing (0), but nil is usually used for an Objective-C object type, while NULL is used for c-style pointers (void *).

Marc Charbonneau
+17  A: 

"nil" should only be used in place of an "id", what we Java and C++ programmers would think of as a pointer to an object. Use NULL for non-object pointers.

Look at the declaration of that method:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context

context is a "void *" (ie a C-style pointer), so you'd definitely use NULL (which is sometimes declared as "(void *)0") rather than nil (which is of type "id").

Paul Tomblin
But since the type of `context` in `observeValueForKeyPath:ofObject:change:context:` is `void *`, doesn't that mean that the data passed as the `context` could be an object pointer? I would think that to be a common case. That's why I'm confused as to why the docs always use `NULL` instead of `nil`.
erikprice
The type of context: in that method is "void *". "nil" is not a "void *", but NULL is.
Paul Tomblin
So is it correct to deduce from this discussion that we *cannot* pass an object pointer (aka, something that can be typed as `nil`) when we pass this message to the object implementing NSKeyValueObserving? Because object pointers cannot be of type `void *` ?
erikprice
To be honest with you, I don't know if you can cast an id into a void*.
Paul Tomblin
You can. void * is any pointer. Nonetheless, you are absolutely right that NULL is the correct constant there.
Peter Hosey
This gets to the meat of my question - why is NULL the correct constant in this case, rather than nil? Given that NULL and nil both have the same "value", what I want to understand is the reasons for using one vs the other - is it intended that context not be an object pointer? It seems deliberate.
erikprice
They said void *. NULL is for void * and nil is for id. Therefore, you pass NULL. If you pass nil, you are lying to your reader, who will think this method takes an id.
Peter Hosey
Peter's got it exactly right - if a function expects a type, and you want to pass a null, pass in the correct null type, not one that just happens to be a subset or have the same internal representation.
Paul Tomblin
Or to think of it another way, NULL is a broader type, and nil is a subset of NULL. In general, use the broadest type you can get away with (ie in Java, write your method to expect a Collection instead of a Vector, unless you need something specific from Vector)
Paul Tomblin
That makes good sense. Thanks to both of you for humoring my persistent questions.
erikprice
I'm glad you understand it better now.
Paul Tomblin
+8  A: 

They're technically the same thing and differ only in style:

  • Objective-C style says nil is what to use for the id type (and pointers to objects).
  • C style says that NULL is what you use for void *.
  • C++ style typically says that you should just use 0.

I typically use the variant that matches the language where the type is declared.

Andrew