In observeValueForKeyPath:ofObject:change:context:
- why do the docs use NULL
instead of nil
when not specifying a context pointer?
views:
7212answers:
3
+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
2009-02-17 16:21:19
+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
2009-02-17 16:23:49
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
2009-02-17 16:38:52
The type of context: in that method is "void *". "nil" is not a "void *", but NULL is.
Paul Tomblin
2009-02-17 16:47:35
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
2009-02-17 17:27:53
To be honest with you, I don't know if you can cast an id into a void*.
Paul Tomblin
2009-02-17 17:57:07
You can. void * is any pointer. Nonetheless, you are absolutely right that NULL is the correct constant there.
Peter Hosey
2009-02-17 18:16:51
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
2009-02-17 18:46:36
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
2009-02-17 18:50:51
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
2009-02-17 18:53:51
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
2009-02-17 18:56:53
That makes good sense. Thanks to both of you for humoring my persistent questions.
erikprice
2009-02-17 21:11:26
I'm glad you understand it better now.
Paul Tomblin
2009-02-17 21:49:58
+8
A:
They're technically the same thing and differ only in style:
- Objective-C style says
nil
is what to use for theid
type (and pointers to objects). - C style says that
NULL
is what you use forvoid *
. - 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
2009-11-05 13:53:52