Uncategorized

Quick iOS: Swift Optionals and nil

TLDR: calling a method on nil will crash. Variables that can be nil are called optional, and are defined using a question mark. To call a method on an optional variable, unwrap it by using a question mark (optional chaining), an exclamation point (force unwrapping), or an if let or guard let statement (conditional unwrapping).

nil is ubiquitous in iOS and Swift code, so knowing what it is, what it does, and how to use it is very important.

nil

In Swift, nil means: nothing is here. Specifically, it means that the variable which is nil is unset. There is no value, it has not been initialized.

What happens when you try to call a function on nil? A crash. Crashes are bad.

Optionals

Optionals help us avoid those crashes. Optionals tell Swift (or rather, the Swift compiler) that the variable could be unset (that is, it could be nil).

Optionals are defined with a question mark, like so:

var name: String? = "Elliot"

That line defines a variable called name, whose type is an optional String, and whose value (currently) is "Elliot". Later on in your code, you might unset this variable by setting it equal to nil, like this:

name = nil

Optional chaining

So, since that variable could be nil, the compiler will refuse to let you call a method on it directly. This is where optional chaining comes in. Optional chaining is basically a way to tell Swift to check if the variable is nil first before calling the method. You can do so by putting a question mark before calling the method; so, for instance, if you wanted to get the first initial of name, you could do this:

name?.prefix(1)

Force unwrapping

Alternatively, if you know that the variable is NOT nil at the point at which you’re calling the method, you can use an exclamation point instead:

name!.prefix(1)

which is called force unwrapping. This is dangerous, though, as if name is nil, your app will crash.

Conditional unwrapping

But what happens if you want to set a non-optional variable with an optional value? Something like this:

var definitelyAName: String = name

This will fail to compile! Swift knows name could be nil, so it won’t let you assign a non-optional variable with it. You could force unwrap as before:

var definitelyAName: String = name!

but it’s better to use conditional unwrapping instead, like so:

if let unwrappedName = name {
  var definitelyAName: String = unwrappedName
}

This if let statement tells Swift: if name is not nil, assign it to a let constant called unwrappedName (whose type will be a non-optional String). Then, within the if, you can do what you need to with it.

A variation on this is guard let. It works similarly to if let, but it allows you to use the unwrapped variable for the rest of the current scope (the function, method, loop, or conditional you’re in). Here’s an example:

guard let unwrappedName = name else { fatalError("oh noes!") }
var definitelyAName: String = unwrappedName

As you can see, you have to provide guard with an else case, so that it has something to do if name is nil.

Nil coalescing

Finally, you could give the variable a fallback value in case name is nil, like so:

var definitelyAName: String = name ?? ""

The double question mark is called the nil coalescing operator, and its job is to provide that fallback value.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s