이 글을 읽기 전에 Optional에 대해 자세히 모르시는 분은
이 글을 먼저 읽고 오시는 것을 추천드립니다. 😊
옵셔널 바인딩(Optional Binding)이란?
Optional Binding은 Optional 타입으로 선언된 변수에 값이 존재하는지 확인하고, 안전하게 값을 추출하는 기법입니다.
옵셔널 바인딩은 if let 또는 if var 구문을 사용하여 옵셔널 값을 안전하게 언래핑(Unwrapping) 할 수 있습니다.
옵셔널 값이 존재하면 if 구문 내에서 해당 값을 사용할 수 있으며, 값이 nil이면 if 구문이 실행되지 않고 건너뛰게 됩니다.
글만으로는 부족하니, 아래 코드를 보면서 보도록 할게요 😋
if let name = optionalName {
print(name) // optionalName의 값이 존재하면 해당 값이 출력된다.
}
//
// optionalName의 값이 존재하지 않는다면, if문을 그냥 지나쳐서 이곳의 코드가 실행된다.
optionalName에 값이 존재한다면 name이라는 변수 안에 실제 값이 저장되고 if구문 내에서 그 값을 사용할 수 있게 됩니다.
하지만, optionalName의 값이 'nil'이라면 if문은 그냥 지나치게 됩니다.
아래의 코드에서 보이듯이 하나의 if문에서 콤마(,)를 사용하여 여러 개의 옵셔널 값을 한 번에 바인딩 할 수 있습니다.
var optionalName: String? = "홍길동"
var optionalCountry: String? = "Korea"
if let name = optionalName, let country = optionalCountry {
// name과 country 값이 존재
}
// name과 country 값이 둘 중 하나라도 존재하지 않는 경우
또한 optional binding을 통해 값을 추출한 후, 조건문을 추가하여 추가적인 작업을 수행할 수도 있습니다.
if let age = optionalAge {
if age >= 20 {
// age의 값이 존재하고, 20살 이상이다.
}
}
Tip!! 코드가 많이 길어질 경우에는 아래와 같이 작성하여 가독성을 높이는 방법도 있습니다.
if let name = optionalName,
let country = optionalCountry {
// name과 country 값이 존재
}
// name과 country 값이 존재하지 않는 경우
옵셔널 체이닝(Optional Chaining)이란?
Optional Chaining은 이름에서 보이듯 "체인처럼 이어진다"는 느낌이라고 생각하시면 될 것 같은데요.
옵셔널 체이닝(Optional Chaining)은 객체의 프로퍼티, 메서드를 연결하여 호출하는 과정에서 nil 여부를 체크하는 방법입니다.
중간에 하나라도 nil이 발견되면, 전체 체이닝의 결과가 nil이 됩니다.
옵셔널 체이닝을 사용하여 프로퍼티에 접근하면, 원래 타입이 Int이든 String이든 상관없이 항상 옵셔널 타입(Int?, String?)으로 반환됩니다. 이렇게 되는 이유는 nil이 반환될 가능성을 고려하여 Swift가 자동으로 옵셔널 타입을 적용하기 때문입니다.
예제 코드를 보면서 설명을 하겠는데요, 아래 예제 코드는 [스위프트 언어 가이드 - Optional Chaining]에 나와있는 예제를 사용하였습니다.
처음으로, 'Person'과 'Residence'라는 두 개의 클래스를 정의합니다.
class Person {
var residence: Residence?
}
// Person 클래스는 Residence 객체를 가리킬 수 있는 옵셔널 프로퍼티 residence를 가지고 있다.
class Residence {
var numberOfRooms = 1
}
// Residence 클래스는 numberOfRooms라는 Int형 속성을 가지고 있으며, 기본값은 1이다.
아래의 코드에서 Person 타입의 인스턴스를 Jud로 생성해 줍니다.
let Jud = Person()
Jud의 프로퍼티 중 residence는 Residence? 타입의 옵셔널 프로퍼티이며, nil이거나 Residence 인스턴스를 가리킬 수 있습니다.
옵셔널 타입은 따로 초기화해주지 않으면 nil로 초기화가 되기 때문에, 위의 코드의 Jud에서 residence 속성 값은 nil이 되겠네요.
let roomCount = Jud.residence!.numberOfRooms
// this triggers a runtime error
위의 코드를 보면 밑에 주석 부분과 같이 오류가 생성됩니다. 그 이유는 Jud의 residence 속성 값이 nil인데, '!'를 사용하여 강제 언래핑(Forced Unwrapping) 하려고 하였기 때문입니다.
아래의 코드는 Jud.residence의 값이 nil이기 때문에, else문으로 넘어가서 코드가 실행되게 됩니다.
if let roomCount = Jud.residence?.numberOfRooms {
print("Jud's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// 출력 결과 : "Unable to retrieve the number of rooms."
위의 에러가 났던 코드에서는 nil인 값을 '!'를 사용하여 강제 언래핑(Forced Unwrapping)을 하려고 해서 오류가 났지만, 이번에는 '?'를 사용하여 강제 언래핑을 하지 않아서 오류는 생성되지 않습니다.
그런데 어느 부분에 옵셔널 체이닝을 사용한 건지를 설명하지 않은거같네요? 어느 부분에서 옵셔널 체이닝을 사용했을까요? 🤔
if let roomCount = Jud.residence?.numberOfRooms
바로 이 부분에 옵셔널 체이닝 방법을 적용하였습니다.
위 코드를 보면 옵셔널 체이닝(?.)을 사용하여 Jud.residence?.numberOfRooms에 접근하고 있습니다. Jud.residence가 nil이 아니라면 numberOfRooms를 확인하여 roomCount 변수에 방 번호가 포함되어 저장되겠네요.
만일, 위의 코드가 if문의 조건을 수행하여 "Jud's residence has 1 room(s)."라는 결과가 나타나도록 하려면,
Jud.residence = Residence()
라는 코드를 추가하면 되겠네요.
Optional에 대해 포스팅할 때 설명했지만, 다시 한번 강조하자면 '!'를 사용하는 '강제 언래핑(Forced Unwrapping)'은 가능하면 사용하지 않는 것이 좋습니다.
그 이유와 '!(강제 언래핑)'을 언제 사용하는지가 궁금하다면, 위에 남겨둔 링크의 Optional 설명 글을 보시는 것을 추천드릴게요 👍
Optional Binding에 대한 설명은 여기까지입니다.
이 글을 읽으신 분들이 있다면 조금이나마 도움이 되길 바라며,
오타나 틀린 점이 있으면 지적해주시면 감사하겠습니다 👋
References
'📌 Swift' 카테고리의 다른 글
[오늘의 Swift 지식] In-Out이란 무엇일까? (0) | 2021.08.24 |
---|---|
[오늘의 Swift 지식] 전달인자(Argument)와 매개변수(Parameter) (0) | 2021.08.13 |
[오늘의 Swift 지식] if let과 guard let의 차이는? (0) | 2021.08.09 |
[오늘의 Swift 지식] 정렬 sort()와 sorted() (0) | 2021.07.17 |
[오늘의 Swift 지식] Optional이란? 🤔 (0) | 2021.07.11 |