안녕하세요~~ 오늘은 옵셔널 추출의 3번째 대안인 옵셔널 체이닝 (Optional Chaining)에 대해 공부를 해보겠습니다. 기존에 배웠던 Force unwrapping의 문제점을 해결할 수 있고 옵셔널 바인딩의 코드를 좀 더 간결하게 줄일 수 있다고 하네요. 그럼 자세하게 알아보도록 하겠습니다.
옵셔널 체이닝이란 이름에서 알 수 있듯이 체인을 이용하여 옵셔널에 접근하는 것입니다. 연속적인 옵셔널들을 연쇄적으로 확인을 해보는 것이죠! 이렇게 옵셔널 체이닝은 옵셔널 바인딩과 강제 언래핑처럼 옵셔널을 완전히 벗겨내는 느낌이 아니라 옵셔널에 접근할때 옵셔널을 다루는 방식이라고 할 수 있습니다.
Force unwrapping : !를 써서 강제로 옵셔널 추출
Optional Binding : if let, guard let을 써서 옵셔널 추출
Optional Chaining : 체인의 형태처럼 연쇄적으로 옵셔널에 접근
어찌보면 옵셔널 바인딩하고 비슷한 느낌으로 옵셔널을 확인해가면서 추출한다고 볼 수 있지만 옵셔널 체이닝은 옵셔널 바인딩하고 다르게 코드를 매우 간결하게 작성할 수 있다고 합니다. 그럼 간단한 코드를 작성해서 더 자세하게 알아보겠습니다.
struct Contacts {
var email : String
var address : [String : String]
}
struct Person {
var name : String
var contacts : Contacts
init(name : String, email : String, address : String) {
self.name = name
contacts = Contacts(email: email, address: ["home" : address])
}
}
var my : Person? = Person(name: "Song", email: "wook4506@naver.com", address: "ilsan")
이렇게 두개의 구조체가 있고 Person구조체에는 Contacts구조체를 인스턴스를 가지는 프로퍼티인 contacts가 있습니다. 또 초기화까지 해주었습니다. 그리고 밑에 변수하나를 만들고 이 변수는 Person의 옵셔널 형태를 띄고 있습니다. 여기서! 이제 값에 접근을 해보겠습니다.
my.name //오류
my.contacts.email //오류
다음과 같은 에러를 확인할 수 있네요. my는 Person의 옵셔널 형태를 띄고 있기 때문에 각 프로퍼티에 접근을 하기 위해서는 반드시 unwrapping을 해야합니다. 그렇다면 어떻게 써야할까요?
my?.name
my?.contacts.email
이렇게 my인스턴스에 ?를 붙여주어서 옵셔널이라는 것을 알려주면 됩니다. 바로 이것이 옵셔널 체이닝이라는 것입니다. my라는 변수가 nil인지 아닌지 확인을 하게 되고 만약 nil이 아닐경우 본래의 값을 반환하고 nil이라면 그냥 nil을 반환하게 됩니다.
위 사진에서 my의 초기값이 있을때 출력과 nil로 바꾼후 출력하여 실행해보았습니다. 초기값이 있을때는 옵셔널에 잘 접근이 되었고 my를 nil로 바꾸니까 아예 nil을 출력하는 것을 볼 수 있습니다.
위에서 언급하였듯이 옵셔널 체이닝은 옵셔널 바인딩과 강제 언래핑처럼 옵셔널을 완전히 벗겨내는 느낌이 아니라 옵셔널에 접근할때 옵셔널을 다루는 방식입니다. 그렇다면 옵셔널을 추출하고 싶을때는 어떻게 해야할까요? 아주 어렵지 않게 생각하셔도 됩니다. 옵셔널 바인딩하고 같이 쓰면 되니까요!!
위에 코드에서 옵셔널 바인딩을 이용한 if let을 추가해보겠습니다.
struct Contacts {
var email : String
var address : [String : String]
}
struct Person {
var name : String
var contacts : Contacts
init(name : String, email : String, address : String) {
self.name = name
contacts = Contacts(email: email, address: ["home" : address])
}
}
var my : Person? = Person(name: "Song", email: "wook4506@naver.com", address: "ilsan")
//my = nil
if let my_email = my?.contacts.email {
print("I have a email : \(my_email)")
}
else {
print("nono..")
}
my는 초기화가 되어서 값이 있으므로 옵셔널 바인딩에 의해 my_email상수로 값이 할당되면서 if문이 실행될 것입니다.
잘 되었네요. 만약 위의 주석이었던 //my = nil을 살린다면 my_email에 값이 할당되지 못하고 else문으로 빠지겠죠! 이렇게 옵셔널 바인딩과 옵셔널 체이닝을 같이 사용하여 옵셔널 값을 추출할 수 있었습니다.
오늘은 옵셔널 체이닝에 대해 공부를 해보았습니다. https://babbab2.tistory.com/32 의 블로그에 정말 정리를 잘 해주셔서 많이 참고해가며 공부를 했네요. 그럼 오늘 하루도 수고 많으셨습니다!