-
Notifications
You must be signed in to change notification settings - Fork 0
[week01] Optional
Daehoon Lee edited this page May 7, 2023
·
4 revisions
-
If Statements and Forced Unwrapping 옵셔널의 실제 값에 상관없이 강제로 값을 추출하는 방법이다. 옵셔널이
nil
일 때 강제추출을 사용하면 런타임 에러가 발생하여 이런 에러를 피하기 위해if
문을 사용해 먼저nil
인지 확인하고 강제추출 방법을 사용한다.if convertedNumber != nil { print("convertedNumber has an integer value of \(convertedNumber!).") }
-
Optional Binding
안전하게 옵셔널 값을 언래핑 하는 방법으로 가장 많이 사용된다.
if
문과guard
문의 가장 큰 차이점은 선언한 임시 상수에 대한 사용 범위(scope)의 차이가 있다.if let
과guard let
비교-
if let
- 옵셔널 값 있으면
if
구문에서 처리하고,nil
이면else
에서 처리한다. - 임시 상수의 사용 범위는
if
문 안에서만 사용 가능하다.
- 옵셔널 값 있으면
-
guard let
- 옵셔널 값이 있으면 다음 코드를 실행하고 아니라면
else
문을 실행한다. - 임시 상수의 사용 범위는 같은 코드 블록 범위이다.
- 옵셔널 값이 있으면 다음 코드를 실행하고 아니라면
if let <#constantName#> = <#someOptional#> { <#statements#> } while let <#constantName#> = <#someOptional#> { <#statements#> } guard let name = person["name"] else { return }
-
-
Implicitly Unwrapped Optionals
강제 추출이나 옵셔널 바인딩처럼, 별도의 추출 과정을 거치지 않아도 자동으로 옵셔널이 해제되는 방법이다.
let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // no need for an exclamation point
-
Optional Chaining
.
을 통해 내부 프로퍼티나 메서드에 연속적으로 접근할 때, 표현식의 옵셔널 값이nil
이면 전체 표현식의 값도nil
이 된다.class Person { var name: String var job: Job? init(name: String) { self.name = name } } class Job { var jobName: String var pay: Int init(jobName: String) { self.jobName = jobName self.pay = 0 } } let hoon: Person? = Person(name: "hoon") hoon?.job?.pay = 400000 // hoon.job은 nil이므로 실행되지 않음 print(hoon?.job?.pay) // -> nil hoon?.job = Job(jobName: "developer") hoon?.job?.pay = 400000 print(hoon?.job?.pay) // -> Optional(400000)
-
nil-coalescing operator
옵셔널 값이
nil
이 아니면 옵셔널을 언래핑한 값을,nil
이면 ?? 뒤의 기본값을 사용한다.var text:String? var output = text ?? "Default value" print(output) // Default value text = "This is a string" output = text ?? "Default String" print(output) // This is a string
예제 코드
// Optional
var productsList: [String?] = ["볼펜", "텀블러", "다이어리", "에코백", "머그컵", "후드집업"]
// !
for (index, product) in productsList.enumerated() {
if product != nil {
print("\(index)번 상품은 \(product!)입니다.")
}
}
// Optional binding: if let
for (index, product) in productsList.enumerated() {
if let product {
print("\(index)번 상품은 \(product)입니다.")
}
}
// Optional binding: guard
for (index, product) in productsList.enumerated() {
guard let product else { continue }
print("\(index)번 상품은 \(product)입니다.")
}
// Optional pattern matching
for (index, product) in productsList.enumerated() {
if case let name? = product {
print("\(index)번 상품은 \(name)입니다.")
}
}
예제 코드
-
throws - throw
를 사용한 예외처리
enum productError: Error {
case empty(Int)
case poor
}
var budget: Int = 2000
var productsList: [String?] = ["볼펜", "텀블러", "다이어리", "에코백", "머그컵", "후드집업"]
//do-catch
func buy(productNumber: Int) throws {
guard let product = productsList[productNumber] else { throw productError.empty(productNumber) }
guard budget >= 1000 else { throw productError.poor }
budget -= 1000
print("\(productsList[productNumber]!) 구매, 현재 잔고는 \(budget)")
productsList[productNumber] = nil
}
for index in [1, 2, 2, 3, 5] {
do {
try buy(productNumber: index)
} catch productError.empty(let index) {
print("\(index)번 상품이 없습니다.")
} catch productError.poor {
print("돈이 부족합니다.")
}
}
예제 코드
-
Result Type
을 사용한 예회처리
enum productError: Error {
case empty(Int)
case poor
}
var budget: Int = 2000
var productsList: [String?] = ["볼펜", "텀블러", "다이어리", "에코백", "머그컵", "후드집업"]
//Result Type
func buy2(productNumber: Int) -> Result<String, productError> {
guard let product = productsList[productNumber] else { return .failure(.empty(productNumber)) }
guard budget >= 1000 else { return .failure(.poor) }
let productName: String = productsList[productNumber]!
budget -= 1000
productsList[productNumber] = nil
return .success(productName)
}
for index in [1, 2, 2, 3, 5] {
let a = buy2(productNumber: index)
switch a {
case .success(let name):
print("\(name) 구매")
case .failure(let error):
print(error)
// case .failure(let error(let x))
// print("aaaa", error)
}
}