Guide
Swift optionals, explained
What the ? on a type means, why Swift will not let you use one as a plain value,
and the four ways to get the value out: ??, if let, guard let and
?..
A value, or nothing at all
An Int always holds a number and a String always holds text. But plenty of honest
questions have no answer: who is at the gate, when nobody is? Swift builds a second type out of the first,
written with a ?:
var arrival: String? = "Sable"
arrival = nil // allowed: String? has room for "nothing"
var name: String = "Sable"
name = nil
// error: 'nil' cannot be assigned to type 'String'
String? is read "optional String", and it is not a String. It is
a box that either holds a String or holds nothing, and nil is the word for the empty
box.
Why Swift will not let you use it directly
let arrival: String? = "Sable"
print(arrival.count)
// error: value of optional type 'String?' must be unwrapped to refer to
// member 'count' of wrapped base type 'String'
That refusal is the whole feature. A program that let this line through would work perfectly — until the day nobody turned up. Swift makes you say what happens then, before the program runs.
?? — the value, or a fallback
let arrival: String? = nil
print(arrival ?? "nobody") // nobody
The optional goes on the left and what to use when it is empty on the right. The result is not optional: the emptiness has been dealt with.
if let — open the box if there is something in it
let arrival: String? = "Sable"
if let arrival {
print("\(arrival) is at the gate.") // Sable is at the gate.
}
Inside the braces arrival is a plain String; outside them it is optional again.
(if let arrival { is short for if let arrival = arrival {.)
guard let — leave early, then carry on
func greet(_ arrival: String?) {
guard let arrival else {
print("Nobody at the gate.")
return
}
print("Welcome, \(arrival).") // a plain String from here on
}
greet("Sable") // Welcome, Sable.
greet(nil) // Nobody at the gate.
guard is the other way round from if let: its else must leave the
function, so the unwrapped name stays available for everything below it. Use it to state what a function
needs at the top, and keep the real work unindented.
?. — reach inside, if there is anything
let arrival: String? = "Sable"
let letters = arrival?.count // an Int?: 5 here, nil with no name
And !, which you rarely want
! insists there is a value. When there is not, the program stops on the spot:
let arrival: String? = nil
print(arrival!)
// Fatal error: Unexpectedly found nil while unwrapping an Optional value
It is a promise about the future. One of the four ways above almost always says what you mean better.
Where SwiftQuest teaches it
Optionals are in Control Flow Keep, the second island, which is free. You predict what
?? prints, run a worked example where somebody (or nobody) is at the gate, and then write and
repair functions with guard let until leaving early feels natural.
Learn it by writing it
SwiftQuest is a Swift course in fifteen islands. Every quest has you write real Swift and run it on a real compiler, in your browser, with nothing to install. It opens soon, and the first two islands are free.