[swift2] 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?

This question is related to swift2 guard-statement

The answer is


One benefit is elimination a lot of nested if let statements. See the WWDC "What's New in Swift" video around 15:30, the section titled "Pyramid of Doom".


Guard statement going to do . it is couple of different

1) it is allow me to reduce nested if statement
2) it is increase my scope which my variable accessible

if Statement

func doTatal(num1 : Int?, num2: Int?) {
  // nested if statement
    if let fistNum = num1 where num1 > 0 {
        if let lastNum = num2 where num2 < 50 {

          let total = fistNum + lastNum
        }
    }
 // don't allow me to access out of the scope 
 //total = fistNum + lastNum 
}

Guard statement

func doTatal(num1 : Int?, num2: Int?) {
   //reduce  nested if statement and check positive way not negative way 
    guard let fistNum = num1 where num1 > 0 else{
      return
    }
    guard  let lastNum = num2 where num2 < 50 else {
     return
    }
    // increase my scope which my variable accessible
    let total = fistNum + lastNum

}

Like an if statement, guard executes statements based on a Boolean value of an expression. Unlike an if statement, guard statements only run if the conditions are not met. You can think of guard more like an Assert, but rather than crashing, you can gracefully exit.

refer to: http://ericcerney.com/swift-guard-statement/


With using guard our intension is clear. we do not want to execute rest of the code if that particular condition is not satisfied. here we are able to extending chain too, please have a look at below code:

guard let value1 = number1, let value2 = number2 else { return }
 // do stuff here

It really really does make the flow of a sequence with several lookups and optionals much more concise and clear and reduces lots of if nesting. See Erica Sadun post on replacing Ifs. .... Could get carried away, an example below:

    let filteredLinks = locationsLinkedToList.filter({$0.actionVerb == movementCommand})
    guard let foundLink = filteredLinks.first else {return ("<Person> cannot go in that direction.", nil, nil)}
    guard filteredLinks.count == 1 else {return ("<Person> cannot decide which route to take.", nil, nil)}
    guard let nextLocation = foundLink.toLocation else {return ("<Person> cannot go in that direction.", nil, nil)}

See if that sticks.


When a condition is met using guard it exposes variables declared within the guard block to the rest of the code-block, bringing them into its scope. Which, as previously stated, will certainly come in handy with nested if let statements.

Note that guard requires a return or a throw in its else statement.

Parsing JSON with Guard

Below is an example of how one might parse a JSON object using guard rather than if-let. This is an excerpt from a blog entry that includes a playground file which you can find here:

How to use Guard in Swift 2 to parse JSON

func parseJSONWithGuard(data : [String : AnyObject]) throws -> Developer {

    guard let firstname = data["First"] as? String  else {
        return Developer() // we could return a nil Developer()
    }

    guard let lastname = data["Last"] as? String else {
        throw ParseError.BadName // or we could throw a custom exception and handle the error
    }

    guard let website = data["WebSite"] as? String else {
        throw ParseError.BadName
    }

    guard let iosDev = data["iosDeveloper"] as? Bool else {
        throw ParseError.BadName
    }



    return Developer(first: firstname, last: lastname, site: website, ios: iosDev)

}

download playground: guard playground

More info:

Here's an excerpt from the The Swift Programming Language Guide:

If the guard statement’s condition is met, code execution continues after the guard statement’s closing brace. Any variables or constants that were assigned values using an optional binding as part of the condition are available for the rest of the code block that the guard statement appears in.

If that condition is not met, the code inside the else branch is executed. That branch must transfer control to exit the code block that that guard statement appears in. It can do this with a control transfer statement such as return, break, or continue, or it can call a function or method that doesn’t return, such as fatalError().


From Apple documentation:

Guard Statement

A guard statement is used to transfer program control out of a scope if one or more conditions aren’t met.

Synatx:

guard condition else {
    statements
}

Advantage:

1. By using guard statement we can get rid of deeply nested conditionals whose sole purpose is validating a set of requirements.

2. It was designed specifically for exiting a method or function early.

if you use if let below is the code how it looks.

  let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

        if error == nil {
            if let  statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 {
                if let data = data {

                    //Process Data Here.
                    print("Data: \(data)")

                } else {
                    print("No data was returned by the request!")
                }
            } else {
                print("Your request returned a status code other than 2XX!")
            }
        } else {
            print("Error Info: \(error.debugDescription)")
        }
    }
    task.resume()

Using guard you can transfer control out of a scope if one or more conditions aren't met.

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

            /* GUARD: was there an error? */
            guard (error == nil) else {
                print("There was an error with your request: \(error)")
                return
            }

            /* GUARD: Did we get a successful 2XX response? */
            guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
                print("Your request returned a status code other than 2XX!")
                return
            }

            /* GUARD: was there any data returned? */
            guard let data = data else {
                print("No data was returned by the request!")
                return
            }

            //Process Data Here.
            print("Data: \(data)")
}
task.resume()

Reference:

1. Swift 2: Exit Early With guard 2. Udacity 3. Guard Statement


Simply put, it provides a way to validate fields prior to execution. This is a good programming style as it enhances readability. In other languages, it may look like this:

func doSomething() {
    if something == nil {
        // return, break, throw error, etc.
    }
    ...
}

But because Swift provides you with optionals, we can't check if it's nil and assign its value to a variable. In contrast, if let checks that it's not nil and assigns a variable to hold the actual value. This is where guard comes into play. It gives you a more concise way of exiting early using optionals.


When to use guards

If you’ve got a view controller with a few UITextField elements or some other type of user input, you’ll immediately notice that you must unwrap the textField.text optional to get to the text inside (if any!). isEmpty won’t do you any good here, without any input the text field will simply return nil.

So you have a few of these which you unwrap and eventually pass to a function that posts them to a server endpoint. We don’t want the server code to have to deal with nil values or mistakenly send invalid values to the server so we’ll unwrap those input values with guard first.

func submit() {
    guard let name = nameField.text else {
        show("No name to submit")
        return
    }

    guard let address = addressField.text else {
        show("No address to submit")
        return
    }

    guard let phone = phoneField.text else {
        show("No phone to submit")
        return
    }

    sendToServer(name, address: address, phone: phone)
}

func sendToServer(name: String, address: String, phone: String) {
  ...
}

You’ll notice that our server communication function takes non-optional String values as parameters, hence the guard unwrapping beforehand. The unwrapping is a little unintuitive because we’re used to unwrapping with if let which unwraps values for use inside a block. Here the guard statement has an associated block but it’s actually an else block - i.e. the thing you do if the unwrapping fails - the values are unwrapped straight into the same context as the statement itself.

// separation of concerns

Without guard

Without using guard, we’d end up with a big pile of code that resembles a pyramid of doom. This doesn’t scale well for adding new fields to our form or make for very readable code. Indentation can be difficult to follow, particularly with so many else statements at each fork.

func nonguardSubmit() {
    if let name = nameField.text {
        if let address = addressField.text {
            if let phone = phoneField.text {
                sendToServer(name, address: address, phone: phone)
            } else {
                show("no phone to submit")
            }
        } else {
            show("no address to submit")
        }
    } else {
        show("no name to submit")
    }
}

Yes, we could even combine all these if let statements into a single statement separated with commas but we would loose the ability to figure out which statement failed and present a message to the user.

https://thatthinginswift.com/guard-statement-swift/


Unlike if, guard creates the variable that can be accessed from outside its block. It is useful to unwrap a lot of Optionals.


There are really two big benefits to guard. One is avoiding the pyramid of doom, as others have mentioned – lots of annoying if let statements nested inside each other moving further and further to the right.

The other benefit is often the logic you want to implement is more "if not let” than "if let { } else".

Here’s an example: suppose you want to implement accumulate – a cross between map and reduce where it gives you back an array of running reduces. Here it is with guard:

extension Sliceable where SubSlice.Generator.Element == Generator.Element {

    func accumulate(combine: (Generator.Element,Generator.Element)->Generator.Element) -> [Generator.Element] {
        // if there are no elements, I just want to bail out and
        // return an empty array
        guard var running = self.first else { return [] }

        // running will now be an unwrapped non-optional
        var result = [running]

        // dropFirst is safe because the collection
        // must have at least one element at this point
        for x in dropFirst(self) {
            running = combine(running, x)
            result.append(running)
        }
        return result
    }

}


let a = [1,2,3].accumulate(+)  // [1,3,6]
let b = [Int]().accumulate(+)  // []

How would you write it without guard, but still using first that returns an optional? Something like this:

extension Sliceable where SubSlice.Generator.Element == Generator.Element {

    func accumulate(combine: (Generator.Element,Generator.Element)->Generator.Element) -> [Generator.Element] {

        if var running = self.first  {
            var result = [running]

            for x in dropFirst(self) {
                running = combine(running, x)
                result.append(running)
            }
            return result
        }
        else {
            return []
        }
    }

}

The extra nesting is annoying, but also, it’s not as logical to have the if and the else so far apart. It’s much more readable to have the early exit for the empty case, and then continue with the rest of the function as if that wasn’t a possibility.


Source: Guard in Swift

Let's see the example to understand it clearly

Example 1:

func validate() {         
    guard 3>2 else {             
    print ("False")             
    return         
    }         
    print ("True") //True     
} 
validate()

In the above example we see that 3 is greater than 2 and the statement inside the guard else clause are skipped and True is printed.

Example 2:

func validate() {         
    guard 1>2 else {             
    print ("False")            //False 
    return         
    }         
    print ("True")      
} 
validate()

In the above example we see that 1 is smaller than 2 and the statement inside the guard else clause are executed and False is printed followed by return.

Example 3: gaurd let, unwrapping optionals through guard let

func getName(args myName: String?) {
     guard let name = myName, !name.isEmpty else {
     print ("Condition is false")          // Condition is false            return         
     }         
     print("Condition is met\(name)")     
} 
getName(args: "")

In the above example we are using guard let to unwrap the optionals. In the function getName we’ve defined a variable of type string myName which is optional. We then use guard let to check whether the variable myName is nil or not, if not assign to name and check again, name is not empty. If both the conditions qualified i.e. true the else block will be skipped and print “Conditions is met with name”.

Basically we are checking two things here separated by comma, first unwrapping and optional and checking whether that satisfies condition or not.

Here we are passing nothing to the function i.e. empty string and hence Condition is false is print.

func getName(args myName: String?) {
     guard let name = myName, !name.isEmpty else {
     print ("Condition is false")          
     return         
     }        
     print("Condition is met \(name)") // Condition is met Hello    
} getName(args: "Hello")

Here we are passing “Hello” to the function and you can see the output is printed “Condition is met Hello”.