나는 Swift에서 Optionals에 대해 읽었으며, if let
Optional이 값을 가지고 있는지 확인하는 데 사용되는 예제를 보았습니다 .
그러나 Swift 2.0에서는 키워드 guard let
가 주로 사용되는 것을 보았습니다 . if let
Swift 2.0에서 제거 되었는지 아니면 여전히 사용할 수 있는지 궁금합니다 .
나는 포함 내 프로그램을 변경해야합니다 if let
에를 guard let
?
나는 Swift에서 Optionals에 대해 읽었으며, if let
Optional이 값을 가지고 있는지 확인하는 데 사용되는 예제를 보았습니다 .
그러나 Swift 2.0에서는 키워드 guard let
가 주로 사용되는 것을 보았습니다 . if let
Swift 2.0에서 제거 되었는지 아니면 여전히 사용할 수 있는지 궁금합니다 .
나는 포함 내 프로그램을 변경해야합니다 if let
에를 guard let
?
답변:
if let
와 guard let
비슷한 역할을하지만, 서로 다른 목적.
의 "else"케이스 guard
는 현재 범위를 종료해야합니다. 일반적으로 이는 return
프로그램을 호출 하거나 중단 해야 함을 의미합니다 . guard
나머지 함수를 중첩하지 않고도 조기 반환을 제공하는 데 사용됩니다.
if let
범위를 중첩하고 특별한 것은 필요하지 않습니다. 할 수 return
있거나 할 수 없습니다.
일반적으로 if-let
블록이 함수의 나머지 부분이되거나 해당 else
절에 a return
또는 abort가 있으면 guard
대신 사용해야합니다 . 이것은 종종 (적어도 내 경험상) 의심스러운 경우 guard
일반적으로 더 나은 대답 임을 의미 합니다. 그러나 if let
여전히 적절한 상황이 많이 있습니다.
guard
오류가 없어도 적절한 경우가 많이 있습니다 . 때로는 할 일이 없음을 의미합니다. 예를 들어 positionTitle
메서드는 guard if let title = title else {return}
. 제목은 선택 사항 일 수 있으며이 경우 오류가 아닙니다. 그러나 guard let
여전히 적절합니다.
if let
는 범위 내 에서만 볼 수 있습니다 if let
. 바인딩 된 변수 guard 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
절이 부작용을 일으킬 때 가드를 피하십시오 . 가드 는 코드가 제대로 실행 되는 데 필요한 조건을 설정 하여 조기 종료를 제공합니다.당신은에서 긍정적 인 지점에서 상당한 계산, 리팩토링을 수행 할 때
if
A와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-let
s에 대한 asserts / 전제 조건을 사용 하지 않습니다. 옳지 않은 것 같습니다)
경비원을 사용하면 운명의 피라미드 를 피하여 선명도를 높일 수 있습니다 . Nitin의 답변을 참조하십시오 .
아무도 잘 설명하지 못했다고 생각하는 중요한 차이점이 하나 있습니다.
모두 guard let
와 if 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 let
do 에 대한 자세한 내용은 다음을 참조하십시오. 선택적 바인딩의 재 선언이 오류를 생성하지 않는 이유
(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!
}
guard
vs if
이 질문을 guard let
vs if let
및 guard
vs 로 보는 것이 더 적절하다는 점은 주목할 가치가 if
있습니다.
독립형 if
은 언 래핑을 수행하지 않으며 독립형도 수행하지 않습니다 guard
. 아래 예를 참조하십시오. 값이이면 일찍 종료되지 않습니다 nil
. 선택적 값이 없습니다. 조건이 충족되지 않으면 조기에 종료됩니다.
let array = ["a", "b", "c"]
func subscript(at index: Int) -> String?{
guard index > 0, index < array.count else { return nil} // exit early with bad index
return array[index]
}
사용 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)
}
필드의 순서가 변경되면 각 코드 줄을 위나 아래로 이동하면됩니다.
이것은 매우 간단한 설명이자 사용 사례입니다. 도움이 되었기를 바랍니다!
내가 본 가장 명확한 설명은 Github Swift Style Guide에 있습니다 .
if
깊이 수준을 추가합니다.
if n.isNumber {
// Use n here
} else {
return
}
guard
하지 않습니다 :
guard n.isNumber else {
return
}
// Use n here
guard
하나 개 이상의 조건이 충족되지 않을 경우 문은 범위의 전송 프로그램 제어 출력에 사용됩니다.
guard
명령문의 조건 값은 유형Bool
이거나에 브리지 된 유형이어야합니다Bool
. 조건은 선택적 바인딩 선언 일 수도 있습니다.
가드 문은 다음과 같은 형식을 갖습니다.
guard condition else {
//Generally return
}
- 선택적 바인딩 으로도 인기가 있습니다.
- 선택적 개체에 액세스하기 위해
if let
.
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 관련 문제
가드 문 가드 블록은 조건이 거짓 인 경우에만 실행되며 리턴을 통해 함수를 종료합니다. 조건이 참이면 Swift는 가드 블록을 무시합니다. 조기 종료와 적은 수의 브래킷을 제공합니다. +
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.
}
Else-If를 사용하여 옵션 래핑 해제
가드 문은 일반적인 조건 블록을 else-if 문으로 대체하는 데 유용 할뿐만 아니라 대괄호 수를 최소화하여 옵션을 풀 때에도 좋습니다. 비교하기 위해 먼저 else-if를 사용하여 여러 옵션을 언 래핑하는 방법을 시작하겠습니다. 먼저, 언 래핑 될 세 가지 옵션을 만들어 보겠습니다.
var publicName: String? = "Bob Lee"
var publicPhoto: String? = "Bob's Face"
var publicAge: Int? = nil
최악의 악몽
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")
}
}
위의 코드는 확실히 작동하지만 DRY 원칙을 위반합니다. 끔찍합니다. 분해합시다. +
약간 더 좋음 아래 코드는 위 코드보다 더 읽기 쉽습니다. +
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
}
}
Guard로 풀기 else-if 문은 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)
}
Else-If로 여러 옵션 래핑 해제 지금까지 옵션을 하나씩 해제했습니다. Swift를 사용하면 여러 옵션을 한 번에 풀 수 있습니다. 그중 하나에 nil이 포함되어 있으면 else 블록을 실행합니다.
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")
}
}
한 번에 여러 옵션을 풀면 nil을 포함하는 것을 식별 할 수 없습니다.
Guard로 여러 옵션을 풀기 물론, 우리는 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
}
if let
할 때 사용non-nil
합니다. 케이스가 일종의 오류를 나타낼guard
때 사용nil
합니다.