DEV Community

loading...

Optionals in Swift

Kate
iOS developer, artist, and aspiring bass guitarist. I started out in front-end web development and shifted over into web production, and am now aiming to become a full-time iOS developer.
Originally published at kduncanwelke.tumblr.com ・4 min read

When I first started learning Swift, I frequently referred to the documentation, but I also visited blogs run by other developers as well. Reading someone else’s explanation of a complex topic often helped my understanding. Now having published to the App Store, it’s time to pass the kindness along, and help other beginner developers get started. 😊

Optionals were a confusing topic early on for me when I was learning Swift, so I will start there.

Optionals

An optional, at its simplest, is either something, or nothing at all. You can pick out an optional easily because each one is declared with a question mark at the end, like so:

var optionalString: String?  
var optionalNumber: Int?
Enter fullscreen mode Exit fullscreen mode

The value is either of the type listed before the question mark (the something), or it is nil (nothing). Optionals do not exist in Objective-C, but nil does, although it has a different meaning (see the docs for more on this). All you need to know for Swift, however, is that nil represents the absence of a value.

You might be wondering why this is a good thing. Why do we want a value to possibly be nothing? What use is nothingness? A good deal of use, surprisingly.

Imagine you have an app, like the Reminders app on your phone. You can enter text for a reminder, and you have the option to set a date for your reminder too. You might want some reminders that have dates, like appointments, and some that don’t, like a chore that isn’t time sensitive. Perhaps you revisit an entry later and assign a date, or decide that a date you added wasn’t necessary, and delete it.

In this situation, a date for any reminder might exist, or it might not . . . sound familiar? Either is has a value, or none at all. That date would be the perfect place to use an optional.

The fact that an optional can be nothing means that it has to be handled carefully, however. If you try to use an optional in a situation where your code expects a value, and the optional happens to be nil, you will get a runtime error (crash).

This error will usually occur when you try to force unwrap an optional. Force unwrapping is done by adding an exclamation point to the end of an optional value like so:

optionalString!
Enter fullscreen mode Exit fullscreen mode

Think of an optional like a present. You must unwrap it to see what’s inside. This implicit unwrapping will open up the optional, but it does so without checking that there is a valid value inside first. If you open it unexpectedly and what’s inside is nil, the present will ‘explode’ and throw a runtime error, causing a crash. It’s best always to open optionals carefully.

Luckily there are a couple of ways to safely unwrap the value, and avoid any exploding gifts.

The first method involves a simple test for nil, followed by a force unwrap. In this case the force unwrap is safe, because we already carefully checked for nil using the ‘not equal’ operator. I would not recommend this as the best method, because these force unwraps are undesirable, but you may see it used.

if optionalString != nil {
    print(“optionalString! is safe to force unwrap because we checked for nil”)
}
Enter fullscreen mode Exit fullscreen mode

The second method is called optional binding. This ‘binds’ the optional to a temporary value. If the optional contains something you can use the temporary value. If the optional is nil, there will be no value assigned and the statement will not be executed. If an else statement is included, this will be executed instead.

Optional binding is commonly achieved through an if let or a guard let. An if let statement, below, exits later and has a limited scope (aka the variable only works inside of it):

if let myString = optionalString {
    print(“here’s myString”)
} else {
    print(“the optional string was nil)
}
Enter fullscreen mode Exit fullscreen mode

A guard let statement, below, exits earlier if the value is nil (at the return), and has a larger scope, because the variable can be used safely after the statement.

guard let myString = optionalString else { 
    print(“the optional was nil”)
    return
}

print(“here’s myString, it can be used now”)
Enter fullscreen mode Exit fullscreen mode

Which binding method you use depends upon your scope requirement and preference.

A third method to handle optionals is to use the nil-coalescing operator, which is represented by ??. If the value on the left-hand side of the ?? is nil, the right-hand side value will be used instead.

This is best used in a case where you wish to supply a default value if nil is present, rather than performing a different action if the value is missing. An example situation might be retrieving album art. If you cannot access an image (aka it is nil), you might supply a default image instead.

let image = albumArt ?? defaultImage
Enter fullscreen mode Exit fullscreen mode

If albumArt is nil, defaultImage will be assigned to image.

To read even more about optionals, visit the documentation page for more: link. And a fun fact you might pick out - an optional is secretly an enum under the hood!

Alt Text

Discussion (0)