5

KEEPING YOUR PROGRAMS SAFE WITH OPTIONALS

In this chapter, we’ll cover a very cool feature in Swift: optionals. Optionals are variables that can either have a value or no value at all. Swift is different from many programming languages because normal constants and variables must have a value. This makes Swift a safe language because it prevents your code from failing when a variable is expected to have a value but one hasn’t yet been set.

However, there will be times when you need to create a variable but don’t have a value for it yet. In these cases, you can use an optional.

WHAT IS AN OPTIONAL?

You can think of an optional as a box that either contains something or is empty. For example, an optional String is just a box that either contains a String or is empty. When an optional is empty, it has the special value nil. In Swift, nil just means that there’s no value.

When you declare a variable or constant, Swift expects it to hold a value. If you’re not sure what value you want that variable or constant to hold, you can use an optional to avoid problems in your programs. Let’s see how!

CREATING OPTIONALS

To create an optional, you declare a variable or a constant and add a ? after the data type. The ? lets Swift know that you want to make the variable or constant an optional. Like a variable or a constant, an optional can contain any data type.

Let’s create an optional called futureTeacher as an example. Imagine that not all of the teachers at your school have been assigned to the next year’s classes yet, so you don’t know who your new teacher will be.

In this example, we create an optional variable, futureTeacher, that will store a String, by adding a ? after the data type. Unlike non-optional variables that we’ve used up until this point, an optional doesn’t require an initial value. That part is—you guessed it—optional! At , we didn’t assign an initial value to futureTeacher, so its default value is the special value nil, which means it doesn’t yet have a value.

Now that we’ve declared futureTeacher as an optional String, it can hold either nothing (nil ) or a String. You change the value of an optional in the same way that you set the value for a regular variable, as shown at . If you change your mind and want to set the optional to nil again, you can do so . Note that you can’t set a regular variable to nil ! This is a special characteristic of optionals. In Figure 5-1, you can see that setting futureTeacher to nil is allowed, but setting grade to nil is not.

The reason you can’t change grade to nil is because grade was not declared as an optional and is just a regular Int data type. Only optionals can hold either a value of the declared type or nil. Optionals are special like that.

Figure 5-1: You can’t set a non-optional to nil.

UNWRAPPING OPTIONALS

Optionals make your code safer because they force you to plan for a situation in which they have no value. But this also means they require a little more work to use.

For example, you can’t use an optional String the same way you would use a regular String. First, you need to check if there really is a String stored in your optional. If there is, then you can use it like any other String.

To check if your optional has a value that you can use, you need to unwrap it. Unwrapping an optional is like taking it out of a box. You wouldn’t play with a birthday present without taking it out of the box, right? Well, you can’t use an optional in your code without unwrapping it first, either. There are a few different ways to unwrap optionals. Let’s see how they work!

Forced Unwrapping

One way to unwrap an optional is through forced unwrapping. Use forced unwrapping when you know that an optional has a value and you want the computer to access that value directly. You do this by entering an ! after the optional name. Enter this code into your playground:

In this example, we set futureTeacher to "Mr.Gale". If we try sticking the optional String variable futureTeacher into a print statement , the value is printed as Optional("Mr.Gale"). That’s not ideal! We just want the string "Mr.Gale". To get that, you need to unwrap the optional. At , we force-unwrap futureTeacher using futureTeacher!. Now the printed line "Next year I know my teacher will be Mr.Gale. " looks as expected.

When you use forced unwrapping, you must be sure that the optional has a value. If it’s nil, you’ll get an error. To see this for yourself, set futureTeacher to nil instead of "Mr.Gale", as shown in Figure 5-2. If you force-unwrap an optional and it has a nil value, your program will crash.

Figure 5-2: Force-unwrapping an optional with no value will cause an error.

Forced unwrapping should be used with caution and only when you can answer yes to the question, “Do I know this optional will always have a value at this point in the code?” You can make sure that an optional has a value by first checking whether it’s equal to nil before trying to unwrap it. This is a safe way to force-unwrap an optional:

At , we check to make sure that futureTeacher has a value before we force-unwrap it. If futureTeacher is not equal to nil, we force-unwrap it and store its value in the constant knownTeacher . If futureTeacher is nil, we print "I do not know who will be my teacher next year." using an else statement at .

Optional Binding

Another way to unwrap an optional is to use optional binding. Optional binding works by temporarily binding the optional to a constant or variable and then providing a block of code that will run only when the optional does have a value. We do this using an if-let statement.

Add this code into your playground to see an if-let statement in action:

The if-let statement checks whether the optional futureTeacher contains a value. If it does, the value will be assigned to the constant knownTeacher , and the block of code in the braces that follows will be executed. In this case, the optional futureTeacher doesn’t contain a value, so the block of code following the if-let statement isn’t executed.

If you want something to happen when your optional has a nil value, then you can write an else block, like we did at . In this example, we’re telling the computer to look at futureTeacher and if it contains a value, the computer should call that value knownTeacher. If there’s no value in futureTeacher, our program will output "I do not know who will be my teacher next year."

Did you notice the similarity between the block of code in the if-let statement and the block of code that you wrote checking whether futureTeacher is nil before force-unwrapping it and setting its value to knownTeacher ? So, for example, this:

if let knownTeacher = futureTeacher {
    print("Next year (knownTeacher) will be my teacher.")
}

is a better and more concise way of writing this:

if futureTeacher != nil {
    let knownTeacher = futureTeacher!
    print("Next year (knownTeacher) will be my teacher.")
}

Try changing futureTeacher to a teacher’s name and run this if-let statement again. You should see the sentence "Next year teacher will be my teacher." filled with the name you typed.

NOTE

Although this type of statement is called an if-let statement, you can also use if-var and temporarily assign the optional value to a variable instead of a constant.

It’s important to note that we’re just temporarily assigning the value in futureTeacher to the constant knownTeacher. The constant knownTeacher only exists inside of the if-let statement’s braces. If you want to access the value of futureTeacher later in the program, you’ll have to make another if-let statement. That’s what we mean when we say that using optionals requires a little more work on your part, because you’ll have to unwrap the optional each time you want to use it.

Optional binding is a safe way to unwrap optionals when you’re not sure if they contain a value. If the optional is nil, you won’t get an error, and instead you can control what happens using an else statement.

You may be asking yourself, “How could you not know whether something has a value?” In our example, it’s quite obvious that futureTeacher doesn’t have a value because we set it to nil. But there are many times when you won’t know whether an optional has a value. For example, suppose we asked the user to input a name for futureTeacher. The user may have typed a name or not. Users can be unpredictable. Maybe they were distracted and forgot to enter a name. There’s no way to see what the user is doing until runtime—that is, when the program is actually running. If our program needs the user to set the value for futureTeacher, then it has to be ready to handle both possibilities (if the user typed a name or forgot) because at runtime either could be true.

Implicitly Unwrapped Optionals

As you have seen so far, optionals need to be unwrapped before your program can access the data they hold. Usually you will unwrap an optional every time you need to use it. But there are some rare cases where you will have a variable that has to be an optional and will always have a value. In these cases, rather than unwrap the optional every time you use it, you can declare it as an implicitly unwrapped optional. This tells the computer that the variable is an optional but will always have a value. An implicitly unwrapped optional, therefore, does not need to be unwrapped every time you use it; it’s automatically unwrapped for you. Instead of creating the optional with a ? after the data type like a regular optional, you create an implicitly unwrapped optional by typing an ! after the data type.

You might be wondering when you would ever use these implicitly unwrapped optionals. A common use is when you write an app with a storyboard. When you want to connect variables in your code to objects in the storyboard, you make them implicitly unwrapped optionals. You’ll see these come up in Chapter 10 while you’re creating the Birthday Tracker app. These variables need to be optional (because the storyboard requires it), but they will always have a value (since they are connected to the storyboard, the storyboard will always give them a value before you use them).

Other than in this special case, you shouldn’t be using implicitly unwrapped optionals very often. They aren’t as safe as regular optionals and can cause your program to crash if used incorrectly. It’s best to stick with regular optionals as much as possible.

A SPECIAL KIND OF OPERATOR: ??

There’s a special kind of operator that’s very useful when you’re unwrapping optionals: the nil coalescing operator. It’s impressive sounding, isn’t it? It’s actually quite easy to use, though, and can be a timesaver.

The nil coalescing operator is written as a pair of question marks between an optional and a default value, like optionalThing ?? defaultThing. When the optional has a value, the value will be used as usual, but when the optional is nil, the nil coalescing operator will use the default value instead.

Let’s try an example with this operator:

At , we create an optional String variable called specialLunch. Next, we set a variable called myLunch to either be the value of specialLunch if it contains a String or defaultLunch if it doesn’t . At , when we print the value of myLunch, we can see that it’s the default value of "pizza" because specialLunch is nil. When we set specialLunch to "shepherd's pie" and then use the nil coalescing operator again, the specialLunch value is unwrapped and put into myLunch . As you can see, the nil coalescing operator is a quick way to either get an optional’s value if it has one, or use some other value if the it is nil.

WHAT YOU LEARNED

In this chapter, you learned about optionals, a great feature that makes Swift a safe language. Optionals force us to know which variables might not have a value so we can prevent any potential problems in our programs.

In Chapter 6, you’ll learn about two collection data types: the array and the dictionary. Both are extremely useful for storing and managing collections of items. Items in an array are stored in an ordered list and can be accessed by an index number. Items in a dictionary are stored in unordered key/value pairs and can be accessed by the keys.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset