2

Look at the following two scenarios with same code:

Using IF LET:

public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?){
    if let error = error {
        print("error: \(error.localizedDescription)")
        return
    }
        for service in peripheral.services!
        {
            print("discovered service is ::::",service)
        }
}

Using GUARD LET:

public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?){
        guard let _ = error else{
            for service in peripheral.services!
            {
                print("discovered service is ::::",service)
            }
        return
       }
    }

Both of them are using return statement and both of them serve the same purpose then what are the differences and which one is better?

EDITS:-

Problem is for general statement it's fine to use any of them but when we have error to handle which one is best to use ?

Shubham Mishra
  • 1,303
  • 13
  • 24
  • 1
    This is a weird function, passing in a error like that. Because of this, it's not well suited to this sort of comparison. – Gary Makin Aug 29 '17 at 11:05
  • 1
    @Shubham Mishra one more + point with guard let is , it also provide use of break,and main purpose is to keep code clean and well readable. – Tushar Sharma Aug 29 '17 at 11:08
  • Problem is for general statement it's fine but when we have error to handle what is best to use ? – Shubham Mishra Aug 29 '17 at 11:19
  • 1
    @ShubhamMishra its your choice which you want . Before guard let was introduced we used if let. But that made code look complex ,lots of nesting and extra use of {}. This was overcome by guard let.Use case is same to handle nil value crash,but also is good to keep code clean and understandable. – Tushar Sharma Aug 29 '17 at 11:28

3 Answers3

3

The usage of guard in this scenario makes your intention clearer—you only want the function to execute if there is no error.

What I like best about guard is that it keeps you from deeply nesting if brackets which makes the code more readable. In your code, to make this happen, you would, however, put it in a format like this:

guard error != nil else { return }
... // continue with regular code

Apart from that guard and if yield the same result—it mostly is a matter of taste.

Tom E
  • 1,530
  • 9
  • 17
3

First of all, None of them is properly implemented.

  • In peripheral.services! if services will be nil, it will crash.
  • Return statement - There is no necessity of return in both, you can just remove it from if-let and everything will work fine
  • The benefit of guard over if-let is it reduces if-else brackets resulting more readable code
  • You use guard if you care about value of variable outside the block scope, think about if-let you can only use unwrapped variable inside block only.
  • Use if-let for small number of variables unwrapping and value of unwrapped variable not required outside block scope
  • Use guard-else for using unwrapped variables outside block scope
  • If you are going to use error object outside the block scope(main use of guard block) then go with guard-else otherwise go with if-let.
Mohammad Zaid Pathan
  • 16,304
  • 7
  • 99
  • 130
2

Guard statements are very good for dealing with "pyramids of doom". The way I'm using it is for example keyboard notification:

func keyboardWillShowSelector(notification:NSNotification) {
        guard let userInfo = notification.userInfo else { return }
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)
        let height = keyboardFrame.size.height
        keyboardWillShow(withHeight: height)
}

Without guard statement it will have another intent and the code will not be so clean:

func keyboardWillShowSelector(notification:NSNotification) {
        if let userInfo = notification.userInfo {
            var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
            keyboardFrame = self.view.convert(keyboardFrame, from: nil)
            let height = keyboardFrame.size.height
            keyboardWillShow(withHeight: height)
        }
}

Another great example is validation:

private func errorFromInputValidation(name: String, email: String, password1: String, password2: String) -> String? {
        guard password1 != "" && password2 != "" && email != "" && name != ""  else { return Localizable.fieldsCannotBeEmpty.localized }
        guard password1 == password2 else { return Localizable.passwordsAreNotEqual.localized }
        return nil
}
Michał Kwiecień
  • 2,734
  • 1
  • 20
  • 23