Skip to content
Theory · Optionals · lesson 1 of 8

A value or nil

What you'll learn

What you'll learn:

  • explain what an optional is and why Int("42") gives Int?, not Int;
  • unwrap an optional with if let and guard let;
  • supply a default value with ?? and read a value through ?.;
  • explain why force unwrapping with ! is dangerous and when it is acceptable.
Two gift boxes Int? with lifted lids — one holds a tile 42, the other a card nil

Imagine someone hands you a gift box. There may be a gift inside, or there may be nothing, and while the box is closed you cannot tell. You cannot use the gift without opening the box: first you open it and look inside.

A program gets boxes like this all the time. Remember type conversion: Int(2.9) always gives the whole number 2. But what if you turn text into a number?

The text "42" holds a number, and the text "forty-two" does not. Swift does not guess and does not stop the program. It answers honestly—with a box that may turn out to be empty:

SWIFT
let first = Int("42")
let second = Int("forty-two")
print(type(of: first))             // Optional<Int>
print(first == nil, second == nil) // false true

Let's go through the program line by line:

  1. Int("42") finds the number 42 in the text and puts it in the box first.
  2. The text "forty-two" has no number in it, and Int(…) returns an empty box. Swift writes emptiness as the word nil.
  3. print(type(of: first)) prints the type of the box—Optional<Int>, not Int.
  4. Comparing with nil answers the question "is the box empty?": first is not empty, and second is.

The type Int?

An optional holds either a value of a given type or nil—"nothing". You write an optional type as an ordinary type with a question mark: Int? reads as "an Int or nothing". The full name of the same type is Optional<Int>, which is what type(of:) showed.

A question mark goes after any type: Double?, String?, Bool?. An optional box has one shape: an Int? holds either a whole number or nothing, but never text.

Where optionals come from

A result that may not exist

Int(…) from text is the first example. The action may fail, and then there is no result. Swift says so through the type: since the result is Int?, it may not be there. Reading the code, you see right away where a check is needed.

A value that does not exist yet

You also declare an optional yourself when the value will appear later. For example, a player's best score is unknown until the first game is played:

SWIFT
var bestScore: Int? = nil
print(bestScore == nil) // true
bestScore = 120
print(bestScore == nil) // false
  1. var bestScore: Int? = nil creates an empty box for a whole number. The type must be written here: from nil alone, Swift cannot tell which box you need.
  2. The first check prints true: the box is empty.
  3. bestScore = 120 puts a number in the box. You do not need to wrap it yourself: Swift does that for you.
  4. The second check prints false.

A plain Int cannot do this. The line let count: Int = nil does not compile: 'nil' cannot initialize specified type 'Int'. An Int always holds a number, and only an optional can be empty.

Int? is not Int

A box with a number is not a number yet. Let's try adding one to first:

SWIFT
print(first + 1) // ✗
TEXT
error: value of optional type 'Int?' must be unwrapped to a value of type 'Int'

The compiler refuses to build the program. The message says: a value of type Int? must be unwrapped to get an Int. Unwrapping is exactly opening the box: checking whether there is a value inside and taking it out. While the box is closed, there is nothing to add: what if it holds nil?

Here the box picture is off. You can shake a real box and guess what is inside. The compiler does not allow guessing: even when you are sure first is not empty, you use the value only after unwrapping it.

Why optionals exist

Interviewers like to ask this: "What is an optional, and which mistake does it prevent?" The answer has two parts:

  • an optional is a type like Int? that holds either a value or nil;
  • the compiler does not let you use an Int? as an Int until the value is unwrapped, so you cannot forget about the empty case.

In many languages almost any value can turn out to be empty. This comes to light only at run time, when the program crashes on the line that used the empty value. In Swift only an optional can be empty, and its type shows that before the program runs.

Common mistake

An optional was printed without unwrapping the value:

SWIFT
print(first) // ✗
TEXT
warning: expression implicitly coerced from 'Int?' to 'Any'

This is a warning, so the program runs. But it prints Optional(42), not 42: print shows the box together with its contents, and prints an empty box as the word nil. Unwrap the value first, and print that.

Key points

  • An optional Int? holds either a value of type Int or nil—"nothing".
  • Int("42") gives Int?: the text may contain no number, and then the result is nil.
  • Int? is not Int: until the value is unwrapped, the compiler will not let you treat it as a number.
  • Only an optional can hold nil, and printing an optional without unwrapping gives a warning.