Best Practices for Using Optionals in Swift

Frustrated by seeing “Fatal error: Unexpectedly found nil while unwrapping an Optional value”?

Yong Cui, Ph.D.
Feb 12 · 7 min read
Photo by Avrielle Suleiman on Unsplash

We use optionals very frequently in our Swift projects. When they’re used improperly, we can encounter this error in Xcode.

Fatal error: Unexpectedly found nil while unwrapping an Optional value

Whenever it happens during an app’s runtime, the app will crash reliably, resulting in an immediate rejection of the app during the App Store’s review process.

Thus, it’s very critical to prevent this from happening — ideally in the app development phase.

In this article, I’ll review the best practices for using optionals in Swift.


What Are Optionals?

Optionals are data types that either represent a value or no value at all.

For example, in the following code, we declare an optional string called name. As you can see, the name variable can have the assigned value of John or have no value after setting it to nil.

After having a first feel with the optional string, let’s see how Apple defines the Optional.

“A type that represents either a wrapped value or nil, the absence of a value.”

The declaration of this data type is the below.

@frozen enum Optional<Wrapped>

As you can tell, it’s a generic enumeration, but what cases does it have? The Optional has two cases.

The none case is the absence of any value, often expressed as nil, while the some(Wrapped) case is the wrapped value of the defined data type, such as Int, String, Dictionary, and custom structs and classes.

Thus, it has been conceptualized by some people that optionals can be viewed as containers of some data types.


Declarations

There are multiple ways to declare an optional. One thing to note is that if we declare an optional, we have to be specific about the wrapped data type, as Optional is a generic enumeration, and thus the use of this generic data type has to involve a concrete data type, such as Int and String.

For example, the following declaration has the error: Reference to generic type ‘Optional’ requires arguments in <…>.

var optionalValue: Optional?

Use trailing question mark

The most common way to declare an optional is to use a trailing question mark (?) following the specific data type.

The following code creates optionals of various data types, including Int, String, Array, Dictionary, struct, and class.

One thing to note is that when we declare an optional of a generic data type, such as Array and Dictionary, we have to be specific about the exact data type of these generic data types.

For example, the following declarations have the errors of using the generic data types without data specificity.

var names: Array?
var information: Dictionary?

To solve this problem, we can just specify the element’s data type for the Array and Dictionary as we did in the above code snippet.

One interesting feature in Swift is that you can append a question mark to an optional data type to make it an optional optional data type, which can repeat multiple times if you want. It’s like something below.

var optional0: String? // an optional String
var optional1: String?? // an optional String?
var optional2: String??? // an optional String??
...and so on

Use the Optional<Wrapped>

Another less-used way to declare optionals is to use the form of Optional<Wrapped>, where Wrapped is the specific data type. The following code snippet shows you the declarations of the same variables shown above.

It should be noted that both ways of declarations have exactly the same effects, but the first one using a question mark is preferred because of its better readability.

Use trailing exclamation mark

Another relatively common way to declare an optional is to add a trailing exclamation mark (!) to a data type (e.g., Int), which are termed Implicitly Unwrapped Optionals.

No worries if you’re unfamiliar with this term because we’ll expand on this concept later in this article. Some relevant code is given below.

As you can expect, the lastName variable is the Optional<String> data type. However, if you append the trailing exclamation mark to an optional that is declared using the Optional<Wrapped> approach, things behave differently.

As you can see for the firstName variable, its type is an optional String?, but not an optional String.

This result shares the same concept of creating optional optionals appending multiple question marks to a data type, like String as we covered in the first part (Use Question Mark section).


Value Assignment

When we declare optionals, we can assign values to these variables if we want. If we don’t assign any values, all optionals have the default “value” — nil, the absence of a value.

The following code shows you how various assignments can be done.

For example, we can use the Optional’s none case to assign to an optional, which makes the variable have a nil value. Similarly, we can use the some<Wrapped> case to assign a value of the wrapped data type to an optional.

Alternatively, we can assign an optional value to an optional variable. In the example, when we use the middleName string to access the key’s value in a Dictionary<String, String>, the return data type is String? type, as it’s likely that the key doesn’t exist in the Dictionary.

Please note that even if we know that the key (e.g., firstName) exists, the return data type is still String? because at runtime, a Dictionary’s key list can always be subject to change.


Unwrap Optionals

To use optionals in most contexts, we need to unwrap optionals to access their wrapped values if not nil. There are different scenarios of how we unwrap optionals as summarized below.

Forced unwrapping

When we’re certain that the optional contains a value, we can use the exclamation mark (!) following the variable name to unconditionally unwrap the value.

Note that when we declare an optional, we use the exclamation mark following a data type, unlike the unwrapping which follows a variable.

Implicit unwrapping

In the Declarations section, we briefly mentioned the concept of Implicitly Unwrapped Optionals. Here, we explain what it is.

Basically, we use an exclamation mark to declare an optional variable of a certain type, let’s say String, and the variable name is called jobTitle.

Every time we use this variable, we can omit the forced unwrapping operator (i.e., post-fix !) to unwrap the optional. In reality, the compiler will unconditionally unwrap this optional for us, and this is why it’s called implicit unwrapping.

Therefore, even though we don’t explicitly use the post-fix ! following the variable, it’s still our responsibility to make sure that the optional is not nil, as forced unwrapping is still happening behind the scene.

When the optional happens to be nil, unwrapping it will lead to the fatal error as shown at the beginning of this article. See some relevant examples below.

Optional binding

Since some behaviors can be unpredictable if we use forced unwrapping, we can use optional binding which conditionally unwraps an optional.

To do that, we can use if let, guard let, and switch, with the former two used more often. The pertinent examples are given below.

Just a couple of notes pertaining to the above code. When we use the if let statement, we can access the named variable in the immediate curly braces (lines 4-6), but not outside them.

By contrast, when we use the guard let statement, the named variable can be accessed outside it (line 15), but not in the immediate curly braces (lines 11-13).

Regarding the switch statement, it’s just because the Optional data type is a generic enumeration, which thus allows us to check an optional value against the none case (i.e., nil).

Optional chaining

Sometimes, we’re OK if an optional is nil and we just don’t perform further operations with the nil optional. In this case, we can use optional binding by using a post-fix question mark (?) following the optional variable.

Here’s an example.

As you can tell, both firstInitial0 and firstInitial1 variables got created successfully as optional Booleans with the former being true and the latter having nil.

In other words, this optional chaining approach allows us to access the optional’s properties and methods safely, because if the optional is nil, it will just assign nil to the declared variable.

Nil coalescing

This is also a very common way to deal with optionals. Basically, we use the nil-coalescing operator (??) to supply a default value to a declared variable if the optional is nil. A simple example is given below.

As mentioned before, the data type of accessing a Dictionary’s element using a key is optional. Depending on the value being nil or not, the default value after the nil-coalescing operator will be assigned to the declared variable as applicable.


Takeaways

This article reviews various aspects regarding the proper use of optionals in Swift. Here’s a quick summary of takeaways.

Best Practices for Optional in Swift

Thanks for reading this article. Happy coding in Swift.

Better Programming

Advice for programmers.

Thanks to Zack Shapiro

Yong Cui, Ph.D.

Written by

Addiction Scientist, iOS/Android Developer, Entrepreneur

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade