-
[Swift/Study] 옵셔널 체이닝Study/ios 2023. 6. 28. 19:51
저번 글에서 강제 옵셔널 추출 방법과 옵셔널 바인딩에 대해 알아봤었다.
https://eunduk2.tistory.com/19
이번 글에서는 옵셔널 체인닝을 공부해보려고 한다.
시작하기 전에 옵셔널 체이닝을 정석적?으로 요약하면
"옵셔널에 속해 있는 nil일지도 모르는 프로퍼티, 메소드, 서브스크립션 등을 가져오거나 호출할 때 사용할 수 있는 일련의 과정" 이다.
일단 옵셔널 체이닝은 처음 접하면 이해하는 것이 생각보다 쉽지 않다.
그래서 한 예시를 들어 설명해보겠다.
저번 글에서 닫힌 상자와 책을 사용하여 강제 추출과 옵셔널 바인딩을 설명했었다.
닫힌 상자안에 책이 있을 수도 있고 없을 수도 있는데 어딘가로 가서 이 책을 읽어야 하는 상황이었다.
강제 추출은 책이 있든 말든 상자째로 들고가서 책을 읽으려는 상황이고
옵셔널 바인딩은 상자를 열어 책이 있나 확인해보고 있으면 자신의 가방에 담아가서 책을 읽는 상황으로 설명했었다.
옵셔널 체이닝에서는 여러개의 상자가 있다고 가정해 보겠다.
닫힌 상자안에 또 다른 닫힌 상자가 있고 그 상자 안에 또 다른 닫힌 상자가 있고 그 안에 책이 있다.
(다시 말하면 1번 상자안에 2번 상자, 2번 상자안에 3번 상자, 3번 상자 안에 책. 러시아 인형처럼)
일단 책이 있다고는 했지만 사실 몇개의 조건을 더 붙여야한다.
책들과 상자들이 없을 수도 있다는 점이다.
예를 들면 1번 상자를 열었는데 2번 상자가 없을 수도 있고 3번 상자까지는 있지만 책이 없을 수도 있다.
어쨌든 옵셔널 체이닝이 하는 일은 상자를 하나씩 열어가면서 다음 상자가 존재하는지를 체크하고 최종적으로 책이 있나 체크한다.
1번 상자부터 책까지 문제 없이 체크되면 책을 가지고 가서 읽을 수 있는 것이고
중간에 상자나 책이 없다는 것을 체크하면 그 즉시 nil을 반환해주는 것이 옵셔널 체이닝이 하는 일이다.
(이해를 돕기위해 설명했는데 더 어려워진 것 같기도 하고..ㅎ)
요약하자면
옵셔널로 되어 있는 멤버(프로퍼티, 메소드, 서브스크립션, 인스턴스, 객체 등)들이
엉겨붙어 있을 때 하나라도 nil이면 nil을 반환하는 것이고 모두 nil이 아니면
최종 값을 반환해주는 것이다.
설명은 여기까지 하고 실습을 통해 연습해보겠다.
내가 이 내용을 야곰 문법책에서 공부하였는데 이 책에서 든 예시를 보여주겠다.
class Room { // 호실 var number: Int // 호실 번호 init(number:Int) { self.number = number } } class Building { var name: String // 건물 var room: Room? // 건물 이름 init(name:String) { self.name = name } } struct Address { // 주소 var province: String // 광역시/도 var city: String // 시/군/구 var street: String // 도로명 var building: Building? // 건물 var detailAddress: String? // 건물 외 상세 주소 } class Person { //사람 var name: String // 이름 var address: Address? // 주소 init(name:String) { self.name = name } }
옵셔널 체이닝 예시를 위해 짜여진 코드이다.
사람의 속성 중 주소 속성이 있는데 주소안에 빌딩, 빌딩안에 호실, 호실안에 호실 번호가 있다.
주소, 빌딩, 호실은 모두 옵셔널 인스턴스이다.
한 명의 사람 인스턴스를 생성하고
// eunduk이라는 사람 생성 let eunduk: Person = Person(name: "eunduk")
이 사람의 호실 번호를 접근한다고 해보자.
그러면
eunduk.address.building.room.number
이런식으로 접근해야 하는데 문제가 있다.
address, building, room은 옵셔널이기 때문에 추출을 해줘야 한다는 것.
강제 추출을 하여 eunduk.address!.building!.room!.number 이렇게 표현할 수 있지만 너무 위험하니 사용안하는 걸로 하고..
옵셔널 바인딩을 이용하면
// eunduk이라는 사람 생성 let eunduk: Person = Person(name: "eunduk") // 호실 번호를 저장할 변수 let optionalEundukRoom: Int? // 옵셔널 바인딩을 통해 호실 번호에 접근 if let eundukAddress = eunduk.address { // address바인딩 if let eundukBuilding = eundukAddress.building { // building바인딩 if let eundukRoom = eundukBuilding.room { // room바인딩 optionalEundukRoom = eundukRoom.number } } }
너무 복잡해져서 사용하기 매우 불편하다.
그런데 옵셔널 체이닝으로 표현하면? (옵셔널에 ? 를 붙여 사용)
// eunduk의 호실 번호에 접근 let optionalEundukRoom: Int? = eunduk.address?.building?.room?.number
이렇게 단 한줄로 표현할 수 있다.
이 부분만 봐도 옵셔널 체이닝이 왜 편하고 왜 쓰여야 하는지 바로 알 수 있다!
그런데 호실 번호를 가져오긴 했지만 여전히 옵셔널 변수에 할당되어 있다. (옵셔널 체이닝은 nil을 반환할 수도 있기 때문에)
그래서 옵셔널 체이닝과 바인딩을 짬뽕해서 사용한다면?
if let roomNumber: Int = eunduk.address?.building?.room?.number { print(roomNumber) } else { print("nil") }
호실 번호를 순수한 int값으로 쓸 수 있게 된다!!
그리고 바인딩을 통해 nil상황에 대해 예외 처리도 가능하다!
물론 값 할당도 체이닝을 통해 당연히 가능하다.
eunduk.address = Address(province: "충청북도", city: "청주시 청원구", street: "충청대로") eunduk.address?.building = Building(name: "곰굴") eunduk.address?.building?.room = Room(number: 0) eunduk.address?.building?.room?.number = 505
마찬가지로 체이닝을한 멤버가 nil이라면 당연히 값 할당을 할 수 없다.
예를 들어 위 코드를 아래와 같이 짠다면
eunduk.address = Address(province: "충청북도", city: "청주시 청원구", street: "충청대로") // 할당 성공 eunduk.address?.building = Building(name: "곰굴") // 할당 성공 //eunduk.address?.building?.room = Room(number: 0) // 주석 처리 eunduk.address?.building?.room?.number = 505 // 할당 실패, room?에서 nil처리가 됨
505라는 정수값을 할당할 수 없다.
글은 여기까지 쓰고 옵셔널 체이닝을 마무리 하도록 하겠다.
사실 옵셔널은 강제 추출, 옵셔널 바인딩, 옵셔널 체이닝만 알아도 쓰는데 지장이 없는 것 같다.
그렇지만 필수적으로 많이 쓰이는 만큼 개념은 확실히 이해하는 것이 중요한 것 같다.
옵셔널 체이닝을 끝으로 옵셔널에 관한 내용을 마무리 하였다.
다음에 또 다양한 문법과 기술들을 공부하여 글을 남기러 오겠습니다😊
'Study > ios' 카테고리의 다른 글
[Swift/Study] TableView 셀을 둥글게 만들고 간격 띄우기 (0) 2023.07.02 [Swift/Study] Realm 속성으로 객체/인스턴스 리스트 (0) 2023.06.30 [Swift/Study] 옵셔널 추출 (0) 2023.06.28 [Swift/Study] 옵셔널이란? (0) 2023.06.28 [ios/Swift] TableView 에서 delegate pattern 사용하기 (0) 2023.03.26