Even though Swift is easy to get started with, developers new to the language need to learn several brand new concepts. The most common hurdle developers run into is understanding optionals. What are they? And how should you deal with optionals?
Another common question developers have when they encounter optionals is "Why?" Why are optionals so important in Swift? In this tutorial, we take a close look at optionals.
What Is an Optional
The underlying concept of an optional is easy to grasp. An optional acts as a container for a value of a particular type. The container holds a value or it doesn't.
An optional acts as a container for a value of a particular type. The container holds a value or it doesn't.
Type safety is a cornerstone of the Swift language. As a result, variables and constants need to be initialized before they can be accessed. From a developer perspective, this is amazing because you know that the variable or constant you are accessing has a value. This isn't true in other languages, such as C and Objective-C.
But you don't always know what the value of a variable or constant will be. If you fetch data from a remote backend, for example, you don't know whether you are going to receive a valid response until the network request has completed. In such scenarios, you need the ability to represent a different state, the absence of a value. And that is where optionals come into play.
Declaring Optionals
To declare an optional, we use a question mark. In the following example, we declare an optional of type String?
or optional String. The question mark indicates that we are dealing with an optional.
var message: String?
Create a playground in Xcode, add the above snippet to your playground, and inspect the output in the results panel on the right. The output should read nil
. In Swift, nil
means no value or the absence of a value. The meaning of nil
in Swift and Objective-C is different. That is very important to understand and remember.
Now add the following line of code to your playground and take a look at the output of the print()
function on the right. Are you surprised? The output indicates that we are dealing with an optional.
var message: String?
message = "I'll be home at six."
print(message)
Unwrapping Optionals
Because the value of an optional is wrapped in a container, you cannot access the value of an optional like you access the value of a variable or constant. The next example illustrates this. Add the following line to your playground.
let body: String = message
The above statement generates an error. Click the red circle on the left to see what the error is about and what Xcode suggests to fix it.
Let's give Xcode's suggestion a try by adding an exclamation mark after the name of the optional. That seems to work fine. But what happens if the optional has no value? Update the example as shown below.
var message: String?
let body: String = message!
When the optional message
doesn't contain a value, an error is thrown. This time Xcode leaves us out in the cold, not giving any hints to fix the problem.
Let's take a moment to discuss what happened and, more importantly, what went wrong. Let me start by explaining the meaning of the exclamation mark. By appending an exclamation mark at the end of an optional, the optional is forced unwrapped. This means that we unwrap the value of the optional's container no matter what it contains. If the optional has a value, we can read the value. If the optional's container is empty, an error is thrown.
Optionals should never be forced unwrapped unless you are absolutely certain it contains a value.
If you force unwrap an optional that doesn't contain a value, your process or application terminates. Optionals should never be forced unwrapped unless you are absolutely certain it contains a value.
Optional Binding
Let's add some safety to the example. Before we assign the value of message
to body
, it is better to first check if the optional contains a value. That is what we do in the following example.
var message: String?
if message != nil {
print(message!)
} else {
print("no value found")
}
This is much safer and we avoid the error we encountered earlier. The downside is that the solution is verbose. We need five lines of code instead of one. Safety comes at a cost.
A more common approach is to use optional binding to safely unwrap the value of the optional. This is illustrated in the next example.
var message: String?
if let unwrappedMessage = message {
print(unwrappedMessage)
} else {
print("no value found")
}
Swift inspects the value of message
and assigns the value to the unwrappedMessage
constant only if message
contains a value. The unwrappedMessage
constant is then available in the if
clause.
If message
doesn't contain a value, the else
clause is executed. The solution is still verbose, but it is easy to read and understand. Optional binding is very powerful. Take a look at the next example to see a more complex example of optional binding.
var name: String? = "AAPL"
var high: Float? = 110.34
var low: Float? = 99.23
if let name = name, let high = high, let low = low {
print("\(name): \(high) - \(low)")
}
What's Next?
Optionals are an important concept of the Swift language. Make sure you understand what an optional is and why they exist. They may feel foreign at first, but, over time, you learn to appreciate them.