Guard Statement

    Problem

    1. Is there any alternative way to write an else-if statement?
    2. 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.

    1. Nested brackets
    2. Have to read every line to spot the error message

    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.

    1. func checkDrinkProgram() {
    2. let iCanDrink = true
    3. guard iCanDrink else {
    4. // if iCanDrink == false, run this block
    5. print("Let's me take you to the jail")
    6. return
    7. }
    8. print("You may drink")
    9. // You may move on
    10. // Come on.
    11. // You may leave
    12. // You don't need to read this.
    13. // Only one bracket on the bottom: feeling zen.
    14. }

    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.

    1. var publicPhoto: String? = "Bob's Face"
    2. var publicAge: Int? = nil

    The Worst Nightmare

    You never want to do this.

    The code below is more readable than above.

    1. func unwrapBetter() {
    2. if let name = publicName {
    3. } else {
    4. print("No name")
    5. return
    6. }
    7. if let photo = publicPhoto {
    8. print("Yes photo")
    9. } else {
    10. print("No photo")
    11. return
    12. }
    13. if let age = publicAge {
    14. print("Yes age")
    15. } else {
    16. print("No age")
    17. return
    18. }
    19. }

    The else-if statements can be replaced with guard.

    1. func unwrapOneByOneWithGuard() {
    2. guard let name = publicName else {
    3. print("Name missing")
    4. return
    5. }
    6. guard let photo = publicPhoto else {
    7. print("Photo missing")
    8. return
    9. }
    10. print("Age missing")
    11. return
    12. }
    13. print(name)
    14. print(photo)
    15. 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.

    Unwrap Multiple Optionals with Guard

    1. func unwrapWithGuard() {
    2. guard let name = publicName, let photo = publicPhoto, let age = publicAge else {
    3. // if one or two of the variables contain "nil"
    4. print("Something is missing")
    5. return
    6. }
    7. print("Your name is \(name). I see your, \(photo). You are \(age).")
    8. // Animation Logic
    9. // Networking
    10. // More Code, but still zen
    11. }

    A defer block only executes only after current scope (loop, method, etc) exits.

    1. func simpleDefer() {
    2. defer { print("Chill, later") }
    3. print("Print First")
    4. }

    Let us execute the simpleDefer() function.

    Another example,

    1. for i in 1...3 {
    2. defer { print ("Deferred \(i)") }
    3. print ("First \(i)")
    4. }
    5. // First 1
    6. // Deferred 1
    7. // First 2
    8. // Deferred 2
    9. // First 3
    10. // Deferred 3
    • Executing completion handler blocks which you will learn in Chapter 3.

    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.