nil / Nil / NULL / NSNull
Understanding the concept of nothingness is as much a philosophical issue as it is a pragmatic one. We are inhabitants of a universe of somethings, yet reason in a logical universe of ontological uncertainties. As a physical manifestation of a logical system, computers are faced with the intractable problem of how to represent nothing with something.
In Objective-C,
there are a few different varieties of nothing:
NULL
, nil
, Nil
, and NSNull
.
Symbol | Value | Meaning |
---|---|---|
NULL |
(void *)0 |
literal null value for C pointers |
nil |
(id)0 |
literal null value for Objective-C objects |
Nil |
(Class)0 |
literal null value for Objective-C classes |
NSNull |
[NSNull null] |
singleton object used to represent null |
NULL
C represents nothing as 0
for primitive values
and NULL
for pointers
(which is equivalent to 0
in a pointer context).
The only time you see NULL
in Objective-C code
is when interacting with low-level C APIs
like Core Foundation or Core Graphics.
nil
Objective-C builds on C’s representation of nothing by adding nil
.
nil
is an object pointer to nothing.
Although semantically distinct from NULL
,
they are technically equivalent.
Perhaps the most notable behavior of nil
,
however, is that it can have messages sent to it without a problem.
In other languages, like Java, this kind of behavior would crash your program.
But in Objective-C,
invoking a method on nil
returns a zero value —
which is to say, “nil
begets nil
“.
This fact alone significantly simplifies things for Objective-C developers,
as it obviates the need to check for nil
before doing anything:
// For example, this expression...
if (name != nil && [name is Equal To String:@"Steve"]) { ... }
// ...can be simplified to:
if ([name is Equal To String:@"Steve"]) { ... }
With vigilance, this quirk of Objective-C can be a convenient feature rather than a lurking source of bugs in your application.
Nil
In addition to nil
,
the Objective-C runtime defines Nil
as a class pointer to nothing.
This lesser-known title-case cousin of nil
doesn’t show up much very often,
but it’s at least worth noting.
NSNull
On the framework level,
Foundation defines NSNull
.
NSNull
defines a class method (+null
)
that returns the singleton NSNull
object.
NSNull
represents nothing with an actual object
rather than a zero value like nil
or NULL
.
NSNull
is used throughout Foundation and other frameworks
to skirt around the limitations of collections
like NSArray
and NSDictionary
not being able to contain nil
values.
You can think of NSNull
as effectively boxing
the NULL
or nil
value so that it can be used in collections:
NSMutable Dictionary *mutable Dictionary = [NSMutable Dictionary dictionary];
mutable Dictionary[@"some Key"] = [NSNull null];
NSLog(@"%@", [mutable Dictionary all Keys]);
// @[@"some Key"]
Why does Objective-C have four values for nothing when one might suffice? It all goes back to a common refrain, about how Objective-C bridges the procedural paradigm of C with Smalltalk-inspired object-oriented paradigm.
In the procedural world of C,
values are indistinguishable from their numeric value.
The same zero value might represent
the first index of an array,
the terminating byte of a string, or
the simply result of “2 - 2”.
Objective-C constructs an object-oriented layer on top of these primitives,
and in so doing establishes a distinct logical universe.
This abstraction allows for a sentinel value,
the NSNull
singleton,
to be defined independently of numbers.
nil
(and Nil
) therefore serve as intermediaries between these worlds
at their convergence point: zero.