Swift Optionals

I saw in a talk by Paul Hudson at NSSpain 2018 that optionals are what people learning Swift struggle with the most. That makes optionals a good topic to cover on a site called Swift Dev Journal.

What Is an Optional?

An optional is a data type for a variable where the variable either exists or doesn’t exist, in which case it’s nil. Pretty much anything in Swift can be an optional, including integers, strings, views, structs, and classes. Add ? to a variable’s type to make that variable an optional.

var description: String?

In this example if there’s a description, the description variable contains a string with the description. If there’s no description, description is nil.

Implicitly Unwrapped Optionals

A special kind of optional is an implicitly unwrapped optional. An implicitly unwrapped optional assumes the value of the optional is not nil. If the value is nil and you access that value in your app, the app crashes. Add ! to a variable’s type to make that variable an implicitly unwrapped optional.

@IBOutlet var textView: UITextView!

Outlets are the most common use of implicitly unwrapped optionals. You can assume your outlets are not nil after loading a storyboard or xib file. If you forget to connect the outlets, your app will crash, but in that case, you want the app to crash so you can connect the outlets.

Outside of outlets you should avoid using implicitly unwrapped optionals because they’re not safe. Every implicitly unwrapped optional in your code is a potential crash.

Force Unwrapping

Force unwrapping an optional uses the value without checking if it’s nil. Add ! to an optional variable to force unwrap it.

print(description!)

Don’t force unwrap implicitly unwrapped optionals. They’re already unwrapped. If you add ! to an implicitly unwrapped optional, you’ll get a compiler error.

Force unwrapping is dangerous. In this example if description is nil, the app will crash.

You should avoid force unwrapping optionals because force unwrapping isn’t safe. Every optional you force unwrap is a potential crash.

Safely Unwrapping with if-let and guard

When writing Swift code, you often end up checking if an optional value is not nil, then assigning a constant with something from the optional value. Suppose you wanted to get a view controller’s parent (which is an optional because a view controller may not have a parent) and do something with it, you could write code like the following:

if parent != nil {
    let parentViewController = parent
    // Do something with parentViewController
}

But this code is a bit tedious to write. Swift provides the if-let statement to combine the nil check and the assignment into one statement.

if let parentViewController = parent {
    // Do something with parentViewController
}

If parent is nil, the code inside the if block won’t execute.

Another way to safely unwrap an optional is to use a guard statement. The guard statement lets you exit quickly if the optional value is nil.

guard let parentViewController = parent else { 
    return 
}
// Do something with parentViewController