swift2guard-statement

Swift's guard keyword


Swift 2 introduced the guard keyword, which could be used to ensure that various data is configured ready to go. An example I saw on this website demonstrates an submitTapped function:

func submitTapped() {
    guard username.text.characters.count > 0 else {
        return
    }

    print("All good")
}

I am wondering if using guard is any different than doing it the old fashioned way, using an if condition. Does it give benefits, which you could not get by using a simple check?


Solution

  • Reading this article I noticed great benefits using Guard

    Here you can compare the use of guard with an example:

    This is the part without guard:

    func fooBinding(x: Int?) {
        if let x = x where x > 0 {
            // Do stuff with x
            x.description
        }
    
        // Value requirements not met, do something
    }
    
    1. Here you’re putting your desired code within all the conditions

      You might not immediately see a problem with this, but you could imagine how confusing it could become if it was nested with numerous conditions that all needed to be met before running your statements

    The way to clean this up is to do each of your checks first, and exit if any aren’t met. This allows easy understanding of what conditions will make this function exit.

    But now we can use guard and we can see that is possible to resolve some issues:

    func fooGuard(x: Int?) {
        guard let x = x where x > 0 else {
            // Value requirements not met, do something
            return
        }
    
        // Do stuff with x
        x.description
    }
    
    1. Checking for the condition you do want, not the one you don’t. This again is similar to an assert. If the condition is not met, guard‘s else statement is run, which breaks out of the function.
    2. If the condition passes, the optional variable here is automatically unwrapped for you within the scope that the guard statement was called – in this case, the fooGuard(_:) function.
    3. You are checking for bad cases early, making your function more readable and easier to maintain

    This same pattern holds true for non-optional values as well:

    func fooNonOptionalGood(x: Int) {
        guard x > 0 else {
            // Value requirements not met, do something
            return
        }
    
        // Do stuff with x
    }
    
    func fooNonOptionalBad(x: Int) {
        if x <= 0 {
            // Value requirements not met, do something
            return
        }
    
        // Do stuff with x
    }
    

    If you still have any questions you can read the entire article: Swift guard statement.

    Wrapping Up

    And finally, reading and testing I found that if you use guard to unwrap any optionals,

    those unwrapped values stay around for you to use in the rest of your code block

    .

    guard let unwrappedName = userName else {
        return
    }
    
    print("Your username is \(unwrappedName)")
    

    Here the unwrapped value would be available only inside the if block

    if let unwrappedName = userName {
        print("Your username is \(unwrappedName)")
    } else {
        return
    }
    
    // this won't work – unwrappedName doesn't exist here!
    print("Your username is \(unwrappedName)")