Programming in Swift: Fundamentals

Oct 19 2021 Swift 5.5, iOS 15, Xcode 13

Part 1: Core Concepts

7. Optionals

Lesson Complete

Play Next Lesson
Next
Save for later
About this episode
See versions

See forum comments
Cinema mode Mark as Complete Download course materials
Previous episode: 6. Challenge: Logical Operators Next episode: 8. Challenge: Optionals

Update Notes: The student materials have been reviewed and are updated as of October 2021.

Optionals can be a point of confusion for beginners in Swift.

Well, to start with, when you see these two things at the end of a bit of code, that indicates you’re looking at an Optional.

To explain what optionals are and why they’re helpful, let’s think about a common problem a programmer might come across.

But what if I was putting someone else into the app, like Ray?

Hey folks? Does Ray have a pet? (off camera: No! He’s allergic!)

No pet! What are we going to do? We need a way to model the concept that Ray doesn’t have a pet.

There are lots of ways you could model this yourself, but you don’t have to! Swift has a great solution for this: optionals.

I think of optionals as a kid-friendly version of Schrödinger’s Cat.

If you’re not familiar with the concept, there’s a box that might have a cat inside, or it might have no cat. The trick is, you won’t know if there’s a cat until you open the box!

Hey! There’s a cat! This Optional had a value of Princess Ozma. Thanks for helping us out, Ozma!

Let’s check another one.

Looks like this one’s nil.

We could use optionals like this to solve our earlier dilemma. We could have an optional box for the cat’s name and there might be a cat’s name inside, or it might be nil.

One more important thing to note: Optionals all have a type.

So if we have an optional cat, you won’t open the optional and find a cacodemon inside!

It’s either going to be a cat, or no cat. An Int, or no Int. A string, or no string.

Now that you’ve got an idea what optionals are about, let’s see what they look like in code.

To create your first optional, let’s use that petName example.

Create a variable called petName and make the type a String:

var petName: String

To turn this into an optional string, all you need to do is add a question mark at the end of the type:

String?
  • You can see in the sidebar that if you don’t give an optional a value right way, the default value is set to nil.

To make this example less sad, change the value to “Mango”

petName = "Mango""
  • In the sidebar, we see the value is set to “Mango”, but if you try to print out the value…
print(petName)
  • you see Optional Mango in the console. That’s because the value is still wrapped up inside the optional.

You’ll get into how to unwrap optionals in just a moment. But first, how do you change an optional back to having no value?

To set an optional back to nil, just use the keyword nil instead of a value.

petName = nil

Now, back to unwrapping optionals. Opening the box you saw earlier, is a lot like unwrapping optionals. You want to get to the actual real value inside that variable, and see if you can work with it.

I’ll make a quick optional int to illustrate something before we really get started.

var result: Int? = 30
  • You know that optionals are typed. This one is an optional Int!

Throughout this course, we’ve encouraged you to use type inference to shorten up your code, but you can’t use type inference when you create optionals.

  • If you get rid of the type, and you’ve given the variable a value,

  • the compiler assumes it’s a regular Int, not an optional Int.

  • And if you change the value to nil,

  • then the compiler has no idea what you want, and you’ll get an error like this one.

So when you declare an optional, you need to explicitly type it, every time!

With your optional properly declared, you’re ready to go back to the problem you saw when you tried to print an optional string

print(result)

We see the same thing with this Optional Int.

If you try to add an Optional Int with an Int…

print(result + 1)

The problem will be spelled out for you! To use the values inside of optionals, you need to unwrap the optional.

Remember, the compiler doesn’t actually know if the optional has a value, or if it’s nil, until you unwrap the optional!

There are several ways to unwrap optionals. The easiest way is called force unwrapping.

To try that out, declare a couple of new variables called petName and petAge:

var petName: String? = "Mango"
var petAge: Int? = 7

I used my dog, again, but you can use any cat or dog or snake or lizard or human that you like.

Now, let’s create another variable to store the unwrapped petname:

var unwrappedPetName = petName!
  • This little exclamation mark at the end is how you force unwrap an optional.

It says “I don’t want to carefully check this optional to see if there’s something inside before I use the contents, I want to open it NOW!”

Now, force unwrapping is the easiest way to unwrap an optional, but it’s also the most dangerous.

In this case, petName has a value, so if you try to print it out using string interpolation…

print("The pet's name is \(unwrappedPetName)")
  • You get the value we expect in the console.

But in the very sad case where there is no pet name…

var petName: String? = nil // "Mango"
  • We get a fatal error that would crash our app. Oh no!

Therefore, you should only use force unwrapping when you absolutely know an optional has a value.

Luckily, there are other ways to safely unwrap optionals! The first one we’ll share is called optional binding.

Optional binding looks very similar to an if else statement:

if let unwrappedPetName = petName {

} else {

}
  • This first line is basically a short hand for this:
// type this above the if let
if petName != nil {
  let unwrappedPetName = petName

Optional Binding used to sound like fancy jargon to me, but what all it means “if this optional is not nil, which means it has a value, store that value in this new constant”.

You are “binding” the value to the constant.

When you use optional binding, it’s very common to name the constant the same as the optional you’re unwrapping:

if let petName = petName {

This technique is called shadowing!

  • This new constant called petName only exists within this block of code, so it won’t conflict with the variable called catName that you declared earlier. You’ll learn more about this idea of “where variables exist” later on in this course when you learn about the concept of “Scope”, but for now, just know that this constant only has effect in this if-else statement, and nowhere else in your code.

What if we wanted to use both petName and petAge at the same time?

With optional binding, you can unwrap multiple things, one right after the other.

if let petName = petName,
   let petAge = petAge {

} else {

}

You just need to comma separate the bindings!

Now you can add a print statement using both of those unwrapped optionals

    print("The pet is \(petName) and they are \(petAge)")
} else {
    print("No pet name or age")
  • When you unwrap multiple optionals like this, it’s a bit like using the And operator. All of the optionals have to have values in order to proceed.

  • If any of the optionals are nil, this code is skipped, and the else statement executes instead.

  • In fact, you could add boolean conditions to this if statement, as well.

There’s one last way I’ll show you to deal with optionals. This one is called “Nil coalescing”.

If we have an optional, like this optional Int:

var optionalInt: Int? = 10

If you absolutely need a value that isn’t nil, you can use the nil coalescing operator to unwrap the optional, and if there’s no value in there, to provide a default value, instead.

var requiredResult = optionalInt ?? 0
  • To use this operator, put the optional you want to check on the left,

  • then the two question marks,

  • then the default value.

  • We can see that, currently, optionalInt has a value of 10, so requiredResult is also 10

If we change optionalInt to nil

 nil //10
  • requiredResult is set to our default value of 0!

Now, I’ve got some optional challenges for you.

Er — I mean, the the challenges are about optionals! The challenges themselves aren’t optional! But there are optionals in the challenges! OK, just go do the challenges, and you’ll see what I mean.