Guard Statement
Introduction
Welcome to Lesson 3 of The Swift Fundamentals. When I started learning Swift for the first time, an else-if
statement made sense. However, a guard
statement rather seemed daunting. In fact, the name doesn’t tell anything about what it does. One day, however, I discovered something. A guard
statement is just another for you to write an else-if
statement. A guard
statement promotes zenness. In other words, it adds clarity, emptiness, and lots of cloud and space. Let us find out through examples.
Zenness: A trait where peace, calmness, and inner awesomeness are all intertwined - Urban Dictionary
Problem
- Is there any alternative way to write an
else-if
statement? - How do you safely unwrap multiple
optionals
?
Typical Else-If
Without having known about guard
, you have used a long else-if
statement to indicate an error message block.
func checkDrinkingAge() {
let canDrink = true
if canDrink {
print("You may enter")
// More Code
// More Code
// More Code
} else {
// More Code
// More Code
// More Code
print("Let me take you to the jail")
}
}
Issues with Else-If
- Nested brackets
- Have to read every line to spot the error message
Guard Statement
A guard
block only runs if the condition is false
, and it will exit out of the function through return
. If the condition is true
, Swift ignores the guard
block. It provides an early exit and fewer brackets.
func checkDrinkProgram() {
let iCanDrink = true
guard iCanDrink else {
// if iCanDrink == false, run this block
print("Let's me take you to the jail")
return
}
print("You may drink")
// You may move on
// Come on.
// You may leave
// You don't need to read this.
// Only one bracket on the bottom: feeling zen.
}
Unwrap Optionals with Else-If
A guard
statement is not only useful for replacing a typical conditional block with an else-if
statement, but also great for unwrapping optionals
by minimizing the number of brackets. To compare, let’s first begin how to unwrap multiple optionals
with else-if
.
First, let us create three optionals
that will be unwrapped.
var publicName: String? = "Bob Lee"
var publicPhoto: String? = "Bob's Face"
var publicAge: Int? = nil
The Worst Nightmare
You never want to do this.
func unwrapOneByOne() {
if let name = publicName {
if let photo = publicPhoto {
if let age = publicAge {
print("Bob: \(name), \(photo), \(age)")
} else {
print("age is mising")
}
} else {
print("photo is missing")
}
} else {
print("name is missing")
}
}
The code above certainly works but violates the DRY principle. It’s atrocious. Let us break it down.
DRY: Don’t Repeat Yourself
Slightly Better
The code below is more readable than above.
func unwrapBetter() {
if let name = publicName {
print("Yes name")
} else {
print("No name")
return
}
if let photo = publicPhoto {
print("Yes photo")
} else {
print("No photo")
return
}
if let age = publicAge {
print("Yes age")
} else {
print("No age")
return
}
}
When Swift encounters
return
, it stops and exits out of the function immediately
Unwrap with Guard
The else-if
statements can be replaced with guard
.
func unwrapOneByOneWithGuard() {
guard let name = publicName else {
print("Name missing")
return
}
guard let photo = publicPhoto else {
print("Photo missing")
return
}
guard let age = publicAge else {
print("Age missing")
return
}
print(name)
print(photo)
print(age)
}
Unwrap Multiple Optionals with Else-If
So far, you’ve been unwrapping optionals
one by one. Swift allows us to unwrap multiple optionals
at once. If one of them contains nil
, it will execute the else
block.
func unwrap() {
if let name = publicName, let photo = publicPhoto, let age = publicAge {
print("Your name is \(name). I see your face right here, \(photo), you are \(age)")
} else {
// if any one of those is missing
print("Something is missing")
}
}
Important: Be aware that when you unwrap multiple
optionals
at once, you can’t identify which containsnil
.
Unwrap Multiple Optionals with Guard
Of course, we should use guard
over else-if
.
func unwrapWithGuard() {
guard let name = publicName, let photo = publicPhoto, let age = publicAge else {
// if one or two of the variables contain "nil"
print("Something is missing")
return
}
print("Your name is \(name). I see your, \(photo). You are \(age).")
// Animation Logic
// Networking
// More Code, but still zen
}
Defer Statement
Defer Statement: Put off (an action or event) to a later time; postpone.
A defer
block only executes only after current scope (loop, method, etc) exits.
func simpleDefer() {
defer { print("Chill, later") }
print("Print First")
}
Let us execute the simpleDefer()
function.
simpleDefer()
// "Print First"
// "Chill, later"
Another example,
for i in 1...3 {
defer { print ("Deferred \(i)") }
print ("First \(i)")
}
// First 1
// Deferred 1
// First 2
// Deferred 2
// First 3
// Deferred 3
Usage Case for Defer
- Executing completion handler blocks which you will learn in Chapter 3.
- Any code you want to explicitly inform your team without requiring them to read the entire function
Source Code
1003_guard_defer_statement.playground
Conclusion
In this lesson, you’ve learned the power of guard
over typical else-if
. First, it provides an early exit. Second, no one has to read the entire function to spot the error messages. You use a guard
statement not just to please yourself, but for the sake of your teammates’ falling hair when he/she reads your code. Keep guarding, everyone. Don’t defer your learning, however.