As per my understanding, NSNull
exists as a replacement of nil
in situations where an object is explicitly required, such in NSArray
and NSDictionary
collections.
One of the good parts of nil
's behavior is that many verbose null
checks can be skipped and it would convenient to have the same behavior implemented by NSNull
. Consider the following example:
NSDictionary * json = // deserialized JSON from a REST service
NSString * name = json[@"first_name"];
if (name != nil && ![name isEqual:[NSNull null]] && [name isEqualToString:@"Gabriele"]) { ... }
the check can currently be simplified to
if (![name isEqual:[NSNull null]] && [name isEqualToString:@"Gabriele"]) { ... }
but if [NSNull null
] was mimicking the behavior of nil
, it could be simplified even more to
if ([name isEqualToString:@"Gabriele"]) { ... }
So my question is why didn't Apple override the -forwardInvocation:
method of NSObject
to mimic the behavior of nil
on an unrecognized selectors?
I would like to get the philosophy behind it and to understand whether there is some drawback or some broken convention that I cannot think of.
My understanding is that nil
's behavior is part of the Objective C language, not of any particular library. NSNull
, on the other hand, is part of a library, with a single very specific purpose:
The
NSNull
class defines a singleton object used to represent null values in collection objects (which don’t allownil
values).
It is not intended for use as a "sentinel" object: if you wish to construct such an object, you can always do so, because collections themselves do not assign NSNull
any particular significance. It is provided for programmers' convenience in situations when they wish to store nil
s, so that programmers could avoid reinventing their own null object every time they need it.
Also note that [NSNull null]
is a singleton, so you can compare it with ==
/ !=
operators instead of calling isEqual:
if (name != [NSNull null] && [name isEqualToString:@"Gabriele"])