if Bool 타입 값 {
// Bool 타입 값이 true일 경우
} else if Bool 타입 값 {
// 첫번째 Bool 타입 값이 false면서
// 두번째 Bool 타입 값이 true인 경우
} else {
// 두 Bool 타입 값이 모두 false인 경우
}
제어문 전환 명령어
(return
, break
, continue
, throw
)를 사용하지 않아도 된다.guard Bool 타입 값 else {
// Bool 타입 값이 false일 경우
return // return, break, continue, throw 등의 제어문 전환 명령
}
// Bool 타입 값이 true일 경우
제어문 전환 명령어
(return
, break
, continue
, throw
)를 반드시 사용해야 한다. 그래서 제어문 전환 명령어를 쓸 수 없는 상황이라면 사용이 불가능하고 함수
, 메서드
, 반복문
등 특정 블록 내부
에 위치하지 않는다면 사용이 불가능히다.for i in 0 ... 3 {
if i == 1 {
print(i)
break
} else {
continue
}
}
// 1
for i in 0 ... 3 {
guard i == 1 else { continue }
print(i)
break
}
// 1
옵셔널 바인딩이란 강제로 옵셔널을 여는 방식(Force unwrapping)이 아닌 안전하게 확인을 해보고 unwrapping하는 방법입니다. 즉, if문을 이용하여 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당을 해주는 방식입니다.
Force unwrapping: !를 써서 강제로 옵셔널 추출
Optional Binding: if let, guard let을 써서 옵셔널 추출
func greet(_ person: [String: String]) {
if let name: String = person["name"] {
print("Hello \\(name)")
} else {
return
}
if let location: String = person["location"] {
print("I hope the weather is nice in \\(location)")
} else {
print("I hope the weather is nice near you")
return
}
}
var personInfo: [String: String] = [String: String]()
personInfo["name"] = "eunseo"
greet(personInfo)
// Hello eunseo
// I hope the weather is nice near you
personInfo["location"] = "Korea"
greet(personInfo)
// Hello eunseo
// I hope the weather is nice in Korea
func greet(_ person: [String: String]) {
guard let name: String = person["name"] else {
return
}
print("Hello \(name)")
guard let location: String = person["location"] else {
print("I hope the weather is nice near you")
return
}
print("I hope the weather is nice in \(location)")
}
var personInfo: [String: String] = [String: String]()
personInfo["name"] = "eunseo"
greet(personInfo)
// Hello eunseo
// I hope the weather is nice near you
personInfo["location"] = "Korea"
greet(personInfo)
// Hello eunseo
// I hope the weather is nice in Korea
Bool 타입 값
으로 분기를 만들 수 있다.옵셔널 바인딩
용도로 사용할 수 있다. 옵셔널 바인딩 된 상수
를 지역상수
처럼 사용 가능합니다.,(쉼표)
로 추가조건
을 나열할 수 있다. AND 논리연산자
와 같은 결과이고, &&
로 치환할 수 있다.제어문 전환 명령어
사용 필수.func enterClub(name: String?, age: Int?) {
guard let name: String = name, let age: Int = age, age > 19, name.isEmpty == false else {
print("You are too young to enter the club")
return
}
print("Welcome \(name)!")
}
enterClub(name: "jenny", age: 15) // You are too young to enter the club
enterClub(name: "eunseo", age: 25) // Welcome eunseo!
공통점에서 설명한 ,(쉼표)
로 추가조건
을 나열하는 모습. AND 논리연산자
와 같은 결과이고, &&
로 치환할 수 있다.
func print(text: String) {
if text.isEmpty { return }
print(text)
}
func print(text: String) {
guard !text.isEmpty else { return }
print(text)
}
이 경우 if 구문은 !가 없어 guard 구문보다 읽기는 쉽지만, return을 하는, Early Exit(빠른 종료)를 하는 경우이기 때문에 guard 구문을 쓰는 것이 더 알맞을 수 있다. !에 거부감이 든다면 String extension(예: isNotEmpty)을 만드는 것도 방법일 수 있다.
func icon() -> UIImage {
if let image = UIImage(named: "Photo") {
return image
} else {
return UIImage(named: "Default")!
}
}
func icon() -> UIImage {
guard let image = UIImage(named: "Photo") else {
return UIImage(named: "Default")!
}
return image
}
if-else 구문의 경우 이것과 저것, 50:50의 느낌을 주지만,
guard 구문의 경우 성공과 실패, 99:1의 느낌을 주기 때문에 이 경우 guard 구문이 더 알맞을 수 있다.
guard let image = UIImage(named: selectedImageName) else { // YESSSSSS
assertionFailure("Missing \(selectedImageName) asset")
return
}
guard let image = UIImage(named: selectedImageName) else { // NOOOOOOO
return
}
guard 구문에서 else 부분에 assertionFailure
을 추가하기를 원하거나 필요로 할 가능성 이 더 높아집니다. 이는 가독성을 향상시키고 예상했던 것을 다른 개발자에게 명확하게 합니다.
일부 (최적화되지 않은) 코드를 사용하여 보호 문의 유용성을 설명하려고 합니다.
이름, 성, 이메일, 전화번호 및 비밀번호를 사용하여 사용자 등록을 위한 텍스트 필드의 유효성을 검사하는 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 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)
}
https://stackoverflow.com/questions/32256834/swift-guard-let-vs-if-let