program story

스위프트 : 가드 vs if let

inputbox 2020. 8. 14. 07:42
반응형

스위프트 : 가드 vs if let


저는 Swift에서 Optionals에 대해 읽었으며, if letOptional이 값을 가지고 있는지 확인하는 데 사용되는 예제를 보았습니다. 그리고 만약 그렇다면 – 언 래핑 된 값으로 무언가를하십시오.

그러나 Swift 2.0에서는 키워드 guard가 주로 사용되는 것을 보았습니다 . if letSwift 2.0에서 제거 되었는지 아니면 여전히 사용할 수 있는지 궁금합니다 .

나는 포함 내 프로그램을 변경해야합니다 if let에를 guard?


if letguard let비슷한 역할을하지만, 서로 다른 목적.

의 "else"케이스 guard는 현재 범위를 종료해야합니다. 일반적으로 이는 return프로그램을 호출 하거나 중단 해야 함을 의미합니다 . guard나머지 함수를 중첩하지 않고도 조기 반환을 제공하는 데 사용됩니다.

if let범위를 중첩하고 특별한 것은 필요하지 않습니다. 할 수 return있거나 할 수 없습니다.

일반적으로 if-let블록이 함수의 나머지 부분이되거나 해당 else절에 a return또는 abort가 있으면 guard대신 사용해야합니다 . 이것은 종종 (적어도 내 경험상) 의심스러운 경우 guard일반적으로 더 나은 대답 임을 의미 합니다. 그러나 if let여전히 적절한 상황이 많이 있습니다.


가드는 선명도 를 향상시킬 수 있습니다.

가드를 사용 하면 가드가 성공할 가능성 이 훨씬 더 높으며 성공 하지 못하면 범위를 일찍 종료하는 것이 다소 중요합니다 . 배열이 비어 있는지 여부에 따라 파일 / 이미지가 있는지 확인하는 것과 같습니다.

func icon() -> UIImage {
    guard let image = UIImage(named: "Photo") else {
        return UIImage(named: "Default")! //This is your fallback
    }
    return image //-----------------you're always expecting/hoping this to happen
}

if-let으로 위의 코드를 작성하면 읽기 개발자에게 50-50 이상임을 전달합니다. 하지만 가드를 사용하면 코드 명확성추가 하고 이것이 95 %의 시간 동안 작동 할 것으로 예상한다는 것을 의미합니다. 실패한 경우 이유를 모르겠습니다. 그럴 가능성은 거의 없지만 ...이 기본 이미지를 대신 사용하거나 잘못된 내용을 설명하는 의미있는 메시지로 단언 할 수 있습니다!

  • guard그들이 부작용을 일으킬 때 s를 피하고 , 가드는 자연스러운 흐름 으로 사용되어야 합니다. else절이 부작용을 유발할 때 가드를 피하십시오 . 가드 는 코드가 제대로 실행 되는 데 필요한 조건을 설정 하여 조기 종료를 제공합니다.

  • 당신은에서 긍정적 인 지점에서 상당한 계산, 리팩토링을 수행 할 때 ifA와 guard문과의 대체 값을 반환 else

From : Erica Sadun의 Swift Style 책

또한 위의 제안과 깨끗한 코드의 결과 실패한 가드 문에 어설 션을 추가하기를 원하거나 필요로 할 가능성높으며 가독성이 향상되고 예상했던 것을 다른 개발자에게 분명하게합니다.

guard​ ​let​ image = ​UIImage​(named: selectedImageName) else { // YESSSSSS
     assertionFailure(​"Missing ​​\(​selectedImageName​)​​ asset"​) 
     return
} 

guard​ ​let​ image = ​UIImage​(named: selectedImageName) else { // NOOOOOOO
​     ​return 
}

From : Erica Sadun의 Swift Style 책 + 일부 수정

( if-lets에 대한 asserts / 전제 조건을 사용 하지 않습니다. 옳지 않은 것 같습니다)

경비원을 사용하면 운명의 피라미드피하여 선명도를 높일 수 있습니다 . Nitin의 답변을 참조하십시오 .


Guard는 변수를 만듭니다.

아무도 잘 설명하지 못했다고 생각하는 중요한 차이점이 하나 있습니다.

모두 guard letif let 포장을 벗긴 변수 그러나

guard let당신이 작성 하는 새로운 변수 가 존재 외부 else문을.

if let당신이 작성되지 않은 새로운 가변 후 다른 문 만 입력 코드 블록을 경우 옵션이 아닌 무기 호입니다. 새로 생성 된 변수 는 코드 블록 내부 에만 존재합니다 .

guard let:

func someFunc(blog: String?) {

    guard let blogName = blog else {
        print("some ErrorMessage")
        print(blogName) // will create an error Because blogName isn't defined yet
        return
    }
    print(blogName) // You can access it here ie AFTER the guard statement!!

    //And if I decided to do 'another' guard let with the same name ie 'blogName' then I would create an error!
    guard let blogName = blog else { // errorLine: Definition Conflicts with previous value.
        print(" Some errorMessage")
        return
    }
    print(blogName)
}

if-let:

func someFunc(blog: String?) {


    if let blogName1 = blog {
        print(blogName1) // You can only access it inside the code block. Outside code block it doesn't exist!
    }
    if let blogName1 = blog { // No Error at this line! Because blogName only exists inside the code block ie {}
        print(blogName1)
    }
}

if letdo 에 대한 자세한 내용은 다음을 참조하십시오. 선택적 바인딩의 재 선언이 오류를 생성하지 않는 이유


가드는 범위를 종료 해야합니다.

(Rob Napier의 답변에서도 언급 됨) :

func 안에guard 정의 해야 합니다. 주요 목적은 조건이 충족되지 않는 경우 범위를 중단 / 반환 / 종료 하는 것입니다.

var str : String?

guard let blogName1 = str else {
    print("some error")
    return // Error: Return invalid outside of a func
}
print (blogName1)

들어 if let당신은 어떤 FUNC 내부에 그것을 할 필요가 없습니다 :

var str : String?    
if let blogName1 = str {
   print(blogName1) // You don't get any errors!
}

사용 if-let시기와 사용시기 guard는 종종 스타일의 문제입니다.

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int항목의 선택적 배열 ( var optionalArray: [SomeType]?) 0이 있고 배열이 nil(설정되지 않음) 또는 count배열에 값이있는 경우 (설정 됨) 를 반환해야 한다고 가정합니다 .

다음을 사용하여 if-let다음 과 같이 구현할 수 있습니다 .

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        if let array = optionalArray {
            return array.count
        }
        return 0
    }

또는 다음과 같이 사용하십시오 guard.

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        guard let array = optionalArray else {
            return 0
        }
        return array.count
    }

예제는 기능적으로 동일합니다.

guard정말로 빛나는 은 데이터 유효성 검사와 같은 작업이 있고 잘못된 경우 함수가 조기에 실패하기를 원할 때입니다.

if-let유효성 검사 완료에 가까워 질 때 일련의 s 를 중첩하는 대신 실패 경로가 모두 이미 반환되었으므로 "성공 경로"와 이제 성공적으로 바인딩 된 옵션은 모두 메서드의 주요 범위에 있습니다.


일부 (최적화되지 않은) 코드로 가드 문의 유용성을 설명하려고 노력할 것입니다.

이름, 성, 이메일, 전화 번호 및 비밀번호로 사용자 등록을위한 텍스트 필드의 유효성을 검사하는 UI가 있습니다.

textField에 유효한 텍스트가 포함되지 않은 경우 해당 필드를 firstResponder로 만들어야합니다.

다음은 최적화되지 않은 코드입니다.

//pyramid of doom

func validateFieldsAndContinueRegistration() {
    if let firstNameString = firstName.text where firstNameString.characters.count > 0{
        if let lastNameString = lastName.text where lastNameString.characters.count > 0{
            if let emailString = email.text where emailString.characters.count > 3 && emailString.containsString("@") && emailString.containsString(".") {
                if let passwordString = password.text where passwordString.characters.count > 7{
                    // all text fields have valid text
                    let accountModel = AccountModel()
                    accountModel.firstName = firstNameString
                    accountModel.lastName = lastNameString
                    accountModel.email = emailString
                    accountModel.password = passwordString
                    APIHandler.sharedInstance.registerUser(accountModel)
                } else {
                    password.becomeFirstResponder()
                }
            } else {
                email.becomeFirstResponder()
            }
        } else {
            lastName.becomeFirstResponder()
        }
    } else {
        firstName.becomeFirstResponder()
    }
}

위에서 볼 수 있듯이 모든 문자열 (firstNameString, lastNameString 등)은 if 문의 범위 내에서만 액세스 할 수 있습니다. 그래서이 "파멸의 피라미드"를 생성하고 가독성과 이동의 용이성을 포함하여 많은 문제를 가지고 있습니다 (필드의 순서가 변경되면이 코드의 대부분을 다시 작성해야합니다).

guard 문 (아래 코드에서)을 사용하면 이러한 문자열이 외부에서 사용 가능 {}하고 모든 필드가 유효한 경우 사용 된다는 것을 알 수 있습니다 .

// guard let no pyramid of doom
func validateFieldsAndContinueRegistration() {

guard let firstNameString = firstName.text where firstNameString.characters.count > 0 else {
            firstName.becomeFirstResponder()
            return
        }
guard let lastNameString = lastName.text where lastNameString.characters.count > 0 else {
            lastName.becomeFirstResponder()
            return
        }
guard let emailString = email.text where 
        emailString.characters.count > 3 &&
        emailString.containsString("@") && 
        emailString.containsString(".") else {
            email.becomeFirstResponder()
            return
        }
guard let passwordString = password.text where passwordString.characters.count > 7 else {
            password.becomeFirstResponder()
            return
        }

// all text fields have valid text
    let accountModel = AccountModel()
    accountModel.firstName = firstNameString
    accountModel.lastName = lastNameString
    accountModel.email = emailString
    accountModel.password = passwordString
    APIHandler.sharedInstance.registerUser(accountModel)
}

필드의 순서가 변경되면 각 코드 줄을 위나 아래로 이동하면됩니다.

이것은 매우 간단한 설명이자 사용 사례입니다. 도움이 되었기를 바랍니다!


기본적인 차이점

가드 렛

  1. 범위에서 초기 존재 프로세스
  2. return, Throw 등과 같은 기존 점수가 필요합니다.
  3. 범위 밖에서 액세스 할 수있는 새 변수를 만듭니다.

하자면

  1. 범위 밖으로 액세스 할 수 없습니다.
  2. 진술을 반환 할 필요가 없습니다. 하지만 우리는 쓸 수 있습니다

참고 : 둘 다 Optional 변수의 래핑을 해제하는 데 사용됩니다.


내가 본 가장 명확한 설명은 Github Swift Style Guide에 있습니다 .

if 깊이 수준을 추가합니다.

if n.isNumber {
    // Use n here
} else {
    return
}

guard 하지 않습니다 :

guard n.isNumber else {
    return
}
// Use n here

가드

  • 가드 문은 하나 이상의 조건이 충족되지 않는 경우 범위 밖으로 프로그램 제어를 전송하는 데 사용됩니다.

  • 가드 문의 조건 값은 Bool 유형이거나 Bool에 브리지 된 유형이어야합니다. 조건은 선택적 바인딩 선언 일 수도 있습니다.

가드 문은 다음과 같은 형식을 갖습니다.

guard condition else {
    //Generally return
}

하자면

  • 옵션 바인딩 으로도 인기
  • 옵션 개체에 액세스하는 우리가 사용 허락한다면
if let roomCount = optionalValue {
       print("roomCount available")
    } else {
        print("roomCount is nil")
 }

나는 밥과 함께 스위프트에게서 이것을 배웠다 ..

일반적인 Else-If

 func checkDrinkingAge() {
      let canDrink = true

     if canDrink {
        print("You may enter")
       // More Code
        // More Code
      // More Code

         } else {
         // More Code
    // More Code
    // More Code
    print("Let me take you to the jail")
          }
     }

Else-If 관련 문제

  1. 중첩 된 괄호
  2. 오류 메시지를 찾기 위해 모든 줄을 읽어야합니다.

Guard Statement 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.+

func checkDrinkProgram() {
       let iCanDrink = true

           guard iCanDrink else {
        // if iCanDrink == false, run this block
         print("Let's me take you to the jail")
          return
        }

         print("You may drink")
           // You may move on
                  // Come on.
                 // You may leave
                // You don't need to read this.
                 // Only one bracket on the bottom: feeling zen.
       }

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.

var publicName: String? = "Bob Lee"
var publicPhoto: String? = "Bob's Face"
var publicAge: Int? = nil

The Worst Nightmare

func unwrapOneByOne() {
         if let name = publicName {
              if let photo = publicPhoto {
                     if let age = publicAge {
                        print("Bob: \(name), \(photo), \(age)")
                                  } else {
                          print("age is mising")
                           }
                  } else {
                      print("photo is missing")
                         }
                  } else {
                        print("name is missing")
                         }
                  }

The code above certainly works but violates the DRY principle. It's atrocious. Let us break it down.+

Slightly Better The code below is more readable than above.+

func unwrapBetter() {
         if let name = publicName {
       print("Yes name")
                   } else {
               print("No name")
        return
      }

         if let photo = publicPhoto {
             print("Yes photo")
            } else {
           print("No photo")
       return
             }

        if let age = publicAge {
            print("Yes age")
                      } else {
                print("No age")
            return
                           }
     }

Unwrap with Guard The else-if statements can be replaced with guard.+

 func unwrapOneByOneWithGuard() {
             guard let name = publicName else {
                  print("Name missing")
              return
                                        }

              guard let photo = publicPhoto else {
              print("Photo missing")
                return
                                            }

                  guard let age = publicAge else {
                   print("Age missing")
                                     return
                                                 }
                 print(name)
                 print(photo)
                 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.

func unwrap() {
  if let name = publicName, let photo = publicPhoto, let age = publicAge {
    print("Your name is \(name). I see your face right here, \(photo), you are \(age)")
  } else {
    // if any one of those is missing
    print("Something is missing")
  }
}

Be aware that when you unwrap multiple optionals at once, you can't identify which contains nil

Unwrap Multiple Optionals with Guard Of course, we should use guard over else-if.+

func unwrapWithGuard() {
  guard let name = publicName, let photo = publicPhoto, let age = publicAge else {
    // if one or two of the variables contain "nil"
    print("Something is missing")
    return
  }

  print("Your name is \(name). I see your, \(photo). You are \(age).")
  // Animation Logic
  // Networking
  // More Code, but still zen
}

참고URL : https://stackoverflow.com/questions/32256834/swift-guard-vs-if-let

반응형