Swift takes a strong stance on which types can be assigned
nil. For example, this is an error:
var i = 1 i = nil //error: nil cannot be assigned to type 'Int' // It is also an error for objects: var obj = NSObject() obj = nil //error: nil cannot be assigned to type 'NSObject'
Many languages struggle to express the notion of absence of value. The problem is that it is often implemented in a way that makes it indistinguishable from the integer
0. It is also often easy to mistake for a pointer. Objective-C suffered from this, and there were several ways to indictate an item has no value:
NSNull. For scalar values, something like
NSIntegerMax was often used.
Swift has a single way to express absence of value for all types. Conversely,
nil indicates the absence of a value and nothing else. The
Optional type is the canonical way to express this absence. It is impossible to mistake a
nil object with the number zero, or for a pointer to memory. You will never question whether a value is
nil or really 0.
This strict separation between value and absense-of-value means you can’t assign
nil just to anything. The literal
nil is assignable only to types which implement the protocol
ExpressibleByNilLiteral. And there is exactly one type in the standard library that implements that protocol: the
Optional enumeration. In other words, you can assign the value
nil only to Optionals.1 Because
nil is not a number, you can’t assign it to an
Optional is generic, so you can have
Optional<NSObject> and so on. The Optional is the type that can take a
nil assignment. An
Optional<Int> either has no value, or it has an intenger value, possibly
If you have an instance that might lack any meaningful value in its lifetime, declare it as an optional. When it has no meaningful value, assign it
var i: Int? = 1 // same as var i: Optional<Int> = 1 var j: Int? // uninitialized optionals are implicitly nil i = nil // Optional accepts nil assignment var obj: NSObject? = NSObject() obj = nil // Optional accepts nil assignment
Also note that these are three very diffent values:
let zeroValue: Int = 0 let nilOptional: Int? = nil let zeroOptional: Int? = 0 zeroValue == 0 // true zeroValue == nil // false nilOptional == 0 // false nilOptional == nil // true zeroOptional == 0 // true zeroOptional == nil // false
If you ever get a compiler error about assigning
nil to a non-optional, this is why. The benefit is that if you ever do encounter a
nil optional, you won’t have to second-guess whether the value is meant to indicate absence of value. This is true whether it it an object you created, or whether you received it from another library.
ExpressibleByNilLiteralon any other type is explicitly discouraged by Apple, and would break the semantic meaning of
nil. Don’t do that. ↩