BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

The guard keyword in Swift: early returns made easy

Paul Hudson    September 23rd 2019    @twostraws

Swift's guard keyword lets us check an optional exists and exit the current scope if it doesn't, which makes it perfect for early returns in methods.

How it used to be: pyramids of doom

When a method runs, you want to be sure that it has all the data it needs to work properly, and your code should only execute when that's the case. Coders solved that in common two ways: pyramids of doom and early returns. The former looks like this:

if firstName != "" {
    if lastName != "" {
        if address != "" {
            // do great code
        }
    }
}

It's called a pyramid of doom because of the natural shape of the code as it piles up with more and more indenting.

The latter looks like this:

if firstName == "" { return }
if lastName == "" { return }
if address == "" { return }
// do great code

This technique is called "early return" because you return from the method as early as possible, meaning that if you remain in the method it means everything is safe.

Neither of these two solutions are attractive. The first solution is messy, and only gets worse as you check more things. By the time you get to the meat of your method, you might be ten levels deep in checks, which is nasty!

The second solution isn't very descriptive, in that it doesn't make clear why we are we returning. It also checks against the opposite of what we care about: we're looking for a valid first name, so checking for an empty string is reversed.

In Swift, early returns have another problem, which is in the way they handle optionals. As you might imagine, one of the most important checks in Swift lies in safely unwrapping optionals, but if you use a straight if/let in your early return, the unwrapped optional will leave scope almost immediately, and you can't use it. You either re-unwrap it, or you force unwrap now that you know it exists. Both are grim.

Introducing Swift's guard statement

There's a Swift keyword called guard, and enables improved early returns in three ways:

  • It makes your intent clearer: you tell guard what you want to be the case rather than the reverse. guard is used specifically for trapping invalid parameters being passed to a method, so everyone will understand what it does when they see it.
  • Any optional variables unwrapped by guard remain in scope after the guard finishes, so you can use them. This means you can check an optional variable is valid by unwrapping it, then use it straight away.
  • It gives you shorter code, which in turn means fewer bugs and happier developers.

Any conditions you would have checked using if before, you can now check using guard. Here are some examples:

guard name.characters.count > 0 else {
    throw InputError.NameIsEmpty
}

guard age > 18 else {
    return false
}

guard #available(iOS 9, *) else {
    return
}

func printName() {
    guard let unwrappedName = name else {
        print("You need to provide a name.")
        return
    }

    print(unwrappedName)
}

That last example shows how unwrapped optionals remain in scope – a key advantage of guard compared to regular early returns.

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.