Unwrapping Optionals in Swift
6 ways to use Optional type in Swift. How many of these methods do you already know? The last one may surprise you!
Introduction
Object references in many programming languages can point to the real object or not point to anything (i.e. they are Null). Swift, conversely, does not have null object references. The references must always point to a real object. To support the “can have absence of a value” feature, Swift has a different solution - the Optional type, which is an enum of two cases.
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
Optional either holds no value or some value. The none enum case denotes the absence of a value and is equivalent to the “nil” literal. The some enum case denotes presence of value and is stored as Wrapped, which is the underlying type of the value. Anytime we have a need to use null, we use Optional.
Lets see an example from an imaginary cat experiment.
func openSchrodingersBox() ->
Cat? {
if poisonFlaskShattered {
return
nil
} else {
return
Cat(name: "Shady")
}
}
This function returns both a value and nil. Also notice that Swift simplifies the syntax to define optional by using trailing question mark (?) instead of typing the full type name Optional<Cat>.
Unwrapping Optionals
Optional instances in Swift must be “unwrapped” before their values can be used. Unwrapping means extracting out the stored value. I will show you 6 ways to unwrap optional values. The following use the example function above to get a cat which may or may not be alive.
let maybeAliveCat:
Cat? = openSchrodingersBox()
1. Optional Binding
The first way you can unwrap an optional is use if-let to find out whether an optional contains a value, and if so, unwrap that value as a new variable. This is called optional binding.
if let aliveCat = maybeAliveCat {
aliveCat.meow()
}
In this example the scope of aliveCat is only within the body of the if statement.
2. Guard Statement
You can use guard statement to also check if optional contains a value. The guard statement has an else clause. The code inside the else clause is executed if the optional doesn’t have a value. If the optional has a value, it is available in the lines of code that follow the guard statement.
guard let aliveCat = maybeAliveCat
else {
return
}
aliveCat.meow()
Using guard statement lets you early exit a method if value is not present. It improves the readability of the code compared to doing the same check with an if statement.
3. Nil-Coalescing Operator
The third way you can unwrap an optional is using the nil-coalescing operator (??). This lets you provide a default value if optional is nil.
let aliveCat = maybeAliveCat ?? defaultCat
aliveCat.meow()
4. Optional Chaining
Next, you can also unwrap by placing a question mark (?) after the optional. This is called optional chaining.
maybeAliveCat?.meow()
If the optional contains a value, the meow() call succeeds; if the optional is nil, the method meow() is never executed. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.
5. Forced Unwrapping
So far we have looked at safe ways to unwrap optionals. These next 2 are unsafe, and should be used when you’re sure that an optional contains a value. First of these is to force unwrap an optional’s underlying value by adding an exclamation point (!) to the end of the optional’s name.
maybeAliveCat!.meow()
This is similar to optional chaining using ?. But the difference is that optional chaining fails gracefully when the optional is nil, whereas trying to use ! to access a nonexistent optional value triggers a runtime error. Therefore, forced unwrapping is generally not recommended.
6. Implicit Unwrapping
Finally, sometimes it’s useful to remove the need to check and unwrap the optional’s value every time it’s accessed, because it can be safely assumed to have a value all of the time. These kinds of optionals are declared using exclamation mark instead of a question mark, and are called as implicitly unwrapped optionals.
let aliveCat: Cat! = maybeAliveCat
aliveCat.meow()
This way optionals are unwrapped automatically and can be used like non-optional values, without the need to unwrap them each time they’re accessed. However, if an implicitly unwrapped optional is nil and you try to access its wrapped value, you’ll trigger a runtime error.
Conclusion
Tony Hoare invented the Null reference in 1965 as part of the ALGOL W language. He later called it as a “billion-dollar mistake”, saying
…it has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
I cannot say if Swift optionals have saved a billion dollars, but I hope at least this article helped you in understanding how to unwrap them. Feel free to contact me if you have any questions or comments.