2

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.

jscs
  • 63,694
  • 13
  • 151
  • 195
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235

1 Answers1

3

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 allow nil 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 nils, 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"])
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thank you for the answer. I'm not sure what do you mean for "sentinel". Anyway my point is that `NSNull` exists as a replacement for `nil`, so in my opinion it would be consistent for it to mimic its behavior. – Gabriele Petronella Aug 22 '13 at 13:58
  • @GabrielePetronella The class exists as a replacement for `nil` in very specific case of storing `nil` in a collection, not as a generic replacement for `nil` constant of the Objective C language. "Sentinel" is a kind of object that you may use to avoid performing a check, for `nil` or otherwise, letting you deal with objects in a uniform way. This is especially useful when your objects are inside a collection. – Sergey Kalinichenko Aug 22 '13 at 14:02
  • Thanks, I think the key relies on the difference levels of the implementations (language and framework). I'm still convinced that having `NSNull` to discard every message would be a sensible implementation, but I'm also starting to grasp the philosophy behind the current one. – Gabriele Petronella Aug 22 '13 at 14:08