Optionals and Guard Statements

Optionals

Optionals are special kinds of variables that can be created when you what to hold a priece of data that might, or might not ever be set. You would use optional variables when you want to store a value that is always required, but might become available. Optional variables (var and let) are created by ending the type definitions with a ? (question mark) symbol.

This allows you to leave the variable or constant unused (set to a value of nil), and allows you to choose to set its value or not. An situation when you might want to use an optional is if you would like to give the option to set a user's middle-name. Not everyone has a middle-name so some users would be leave that value unset.

The following is an example of creaing an option String.

var userName: String? = "Jon Doe"
1

When you want to access the value within an optional variable you must "unwrap" the optional. This is done when you use the optional variable by adding an ! after the nvariable name like so.

print(userName!)
1

WARNING

Trying to unwrap and use an optional variable that is still set to nil will cause your application to crash!

You should never try to use optional variables without first checking if there is a valid value set first. The following example will generate an error in your code. The following is an example of creaing an option String.

var userEmail: String?

print(userEmail!)
1
2
3

Binding of Optionals

There a a few ways to vlidate if an optional have been set with a value before you use it. The first way is using what is called Optiona-Binding. In the example below you can see how to validate if an optional is set to nil, or set to a valid value by binding it to a new constant (let) variable created within an if-statement.

/*
The following optional var called userAge will be will be bound to below. 
Uncomment the end of the following line to see the binding condition change.
*/
var userAge: Int? //= 39

// Use an if statement, checking if optional value above is nil or not
if let userAge = userAge {
    // If the variable has a valid value
    print("uaerAge has a value of: \(userAge)")
} else {
    // the optional still has a value of nil
    print("Error: userAge = nil.")
}

/*
 The following example shows binding of 3 optional strings and checks them all.
 If any of the 3 let values we try and bind to fail (return nil), the if
 statement fails. You can choose to bind to vars, too, and the names of the
 values you bind is up to you.
 */

var userName: String? = "Amber"
var userPassword: String? = "abc123"
var userEmail: String? //= "a@b.com" // Uncomment to see condition change

// Use an if statement, checking if you can access the above values in question
if let safeUserName = userName, let safeUserPassword = userPassword, let safeUserEmail = userEmail {
    // Each new bound variable was created and set to a non-nil value
    print("Account created successfuly for \(safeUserEmail). \nWelcom \(safeUserName).")
} else {
    // One of the values was nil
    print("Error: All fields must be filed out.")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

Swift Fundamentals - Optionals - An Introduction Pluralsight

Swift Fundamentals - Unwrapping Your Optionals Pluralsight

Guard Statements

The guard statement is used for the opposite reason of an if statement. With an if statement, the idea is to execute a statement's block of code if the condition is true.

The guard statement lets a block of code run if a condition is false. A guard statement must contain an else clause that gets triggered if the condition fails. A guard must also end with a control-transfer statement, which means that guard statements can only be used inside of other flow-control statements.

If the guard statement succeeds, the rest of the code within the flow-control that follows after it will be allowed to run. If the guard statement fails, the control-transfer statement in the else clause is used to end execution within the flow-control statement immediately.

The code below demonstrates how to use a guard statement to prevent code from running or not.

// Create an optional strings and set it to a value for the guard statement to work
var emailAddress: String? //= "a@b.com" // Uncomment to see change

// Create a function to use the guard on that takes an optional string as its parameter
func checkEmail(email: String?) -> String {
    // Create a guard statement that hope will succeed, and pass this guard
    guard email != nil else {
        // if the statement fails the guard will return out of the function prematurely
        return "Error: A valid email must be entered."
    }
    // If the values in the statement passes the guard the code after will execute
    print("Email accepted")
    return "The email address \(emailAddress!) has been accepted."
}

print(checkEmail(email: emailAddress))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Swift Fundamentals - Using Guard and Defer Pluralsight

Get-Only Variables

Another helpful use for a guard statement is to use the to make get-only variables. This is where you create a variable to safely access another optional variable safely without the need to worry if it has been set or not. By creating the additional "safe" get-only variable you can predetermine what value gets returned when the original value is still nil.

// Create an optional variable
var myNum: Int? //= 25  // Uncomment to set optional

/* Make a Get-Only variable that returns a 'safe' value for the above
optional if it is nil, otherwise return the unwrapped optional value */
var currentNumber: Int {
    guard myNum != nil else { return 0 }
    return myNum!
}

// You can access the current Get-Only variable like a normal variable
var e = currentNumber

// But you can not set its value directly 
// currentNumber = 34
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Back to Week 3

Last Updated: 9/25/2020, 5:14:52 AM