Optionals are not Optional
Defining an object’s existence with Swift
One of the hardest concepts for a programming language (or any language really) to tackle is that of the non-existence of an object. Swift uses the term
nil to denote an absence of an object. On the surface, it doesn’t seem like it would mean much, but digging deeper uncovers a myriad of pitfalls that a developer could potentially hit when working in a language that has such a conceit. What happens if you attempt to access that object in a dangerous way? How do you know an object could be nil? How do you ensure it’s not nil when working with it?
With Swift, the solution is optionals. You can denote an object as an optional by adding a
! to the type when you define it. Take the Lord of the Rings character Gollum for instance. At certain points during the story, he has the Ring, at other times he doesn’t. If we were creating a Gollum struct or class we could use optionals to model that scenario.
Our Gollum struct has a variable called
theRing which is an optional
TheOneRing object. When Gollum has control of the ring, this is set to a value. When he does not,
Before we dive headfirst into using optionals, let’s take a closer look at what they are. An optional is nothing more than an enum with two cases:
.none. When your optional holds an object, the
.some case has an associated value, when it does not, the
.none case indicates your optional is
nil. This means you could handle optional values the same way you handle any other enum in Swift. Using our
theRing example from above, it would look like this:
This is just a switch statement over
theRing object. If it has an associated value, then it will fall into the
.some case and
theRing will be printed, if not then it falls into the
.none case and
Nothing here will be printed.
One of the great things about Swift is this is all handled for you through a process known as unwrapping. Let’s start with a new example before digging into how to unwrap optionals. Since many people equate software development to magic, we’ll use a magician putting on a magic show. First, we define the
In our example, there are two things that define a
Magician: they may or may not use a prop, and they have the ability to do a trick. Next, we’ll create a function that takes an optional
Because the magician is optional (denoted by
?) we have to unwrap it to see if it holds a value. One of the simplest ways to do this is through the use of the
? operator itself. Let’s see how that would work with our
That’s it! If the
magician parameter holds value, then that object is unwrapped and its
doTrick() function is called. If instead, it’s
nil, then when
attemptTrick(with: Magician?) is called, nothing happens.
Another use of the
? operator is optional chaining. Say you have an optional type that has another optional type nested inside of it and you want to access an attribute of the nested optional type. Our Magician type has an optional Prop type, let’s define the Prop type now with an optional attribute
isAvailable that will mimic whether the prop is available or not.
Now we can use optional chaining to get to the
isAvailable attribute from our magician.
Note that the return type of the function is an optional bool. This is because if neither the magician or the prop has value, the function will return nil.
That doesn’t make much sense though. The prop either is or is not available, there’s never really a time when it can be anything else. Let’s use a new technique known as
if let to unwrap our optionals and clean up the function. When using
if let syntax, you’re basically saying “if I can let my object be what I’m unwrapping, do the code in the curly braces”. It follows the same type of logic as any other if statement. The one thing to keep in mind is that the object you unwrap is only available within the scope of the if statement, it doesn’t exist outside of the curly braces.
I read this as saying “if I can let prop be equal to the magician’s prop, return true, else return false”. Not only does this function now return an actual value every time, it also means you can clean up the Prop type by eliminating the
Using Guard Statements
if let is nice, I prefer the use of another unwrapping technique known as guard statements. Guard statements have the advantage of being slightly easier to read syntactically as well as allowing your unwrapped object to be available within more of the scope. Here is our
isPropAvailable function using
So far we’ve used the
? operator exclusively in our code, now let’s take a look at its mischievous twin, the
! operator. Using
! to unwrap an optional is known as force unwrapping. It essentially means that you know your optional has a value. In fact, you’re so sure that it holds a value that you’re willing to risk crashing your app if it does not. That’s the consequence of using
!: If it’s done poorly, your app stops running. You may be asking yourself “if the consequence is so steep, why would I ever use it?”. What if you’re writing a piece of code and you want to be absolutely positive that your app is in a certain state before continuing? If it’s not in the correct state, it may be better off crashing than to continue running. Here is our updated example with force unwrapping:
This example is admittedly tongue-in-cheek. If the building you were seeing the magician perform in were on fire, your last worry would be that the magician wasn’t there to do the trick.
Substituting for Nil
The final piece of optionality I’d like to cover is the nil-coalescing operator
??. This operator allows you to substitute an object for nil. Picture our magician falling ill and having an understudy replace him for the event. It looks like this:
This function will take your first choice of magician, but if that magician returns nil, it will create a new instance of the magician type and return that instead. You will always have a magician for the show!
Some consider optionals to be the toughest part of the language to understand. They certainly confused me when I first started learning Swift. I came from a Java background where optionals don’t exist. Instead, you learned to check for
null before using a value. The alternative is to crash. In my opinion, optionals are one of the biggest advantages Swift has over a language like Java. Yes, there is a learning curve associated with them, but becoming well-versed in their uses will make a substantial difference in how you write apps.