- Total
꿈꾸는리버리
[2/2] optional chaining 본문
이전 포스팅에서 optional의 개념과 optional을 unwrapping하는 방법에 대해서 알아봤는데,
느낌적으로 optional binding을 하는 게 최고구나 ! 라는 것을 느꼈을 거다 ㅎㅎ
💡 optional chaining
이제 더 나아가서 optional binding과 함께 사용하면 좋은 optional chaining에 대해서 알아보자 !
하단에는 한 사람의 주소를 나타내기 위한 struct들이다..
person -> address -> building -> room 이렇게 접근이 된다.
struct Person{
var name : String
var address : Address?
}
struct Address{
var city : String
var building : Building?
}
struct Building{
var name : String
var room : Room?
}
struct Room{
var number : Int
}
address, building, room은 모두 옵셔널이라는 것을 명심한 채 하단의 내용을 읽어보길 바란다..!
river.address?.building?.room?.number
이 뜻은
river.address? -> address가 nil이 아니야? 그럼 building 확인
river.address?.building? -> building이 nil이 아니야? 그럼 room 확인
river.address?.building?.room?.number -> room이 nil이 아니야? 그럼 number 확인
요론 느낌 ? 으로 이해를 하면 된다.
그래서 number를 확인하기 이전의 단계에서 nil이라는 게 확인이 되면 뒤에꺼는 확인하지 않고 nil을 반환한다.
let river : Person = Person(name: "River")
var river2 : Person = Person(name: "River",address: Address(city: "Busan", building: Building(name: "빌딩이름", room: Room(number: 1004))))
let riverRoomNumber : Int? = river.address?.building?.room?.number
var river2RoomNumber : Int? = river2.address?.building?.room?.number
// 에러 발생 (!은 강제 unwrapping 이라서 nil일 때 런타임 에러가 발생한다. )
//let riverRoomNumber2 : Int? = river.address!.building!.room!.number
// + 요론 식으로 값을 대입할 수도 있다.
river2RoomNumber = 100
위에서 number 값을 riverRoomNumber에 대입하는 과정을 optional binding으로 적으면 하단의 코드와 같다.
var river2 : Person = Person(name: "River",address: Address(city: "Busan", building: Building(name: "빌딩이름", room: Room(number: 1004))))
if let address = river2.address{
if let building = address.building{
if let room : Int = building.room{
print(" room 번호 : \(room.number)")
}
}
}
한눈에 봐도 알겠지만 위의 optional chaining이 훨씬 가독성이 좋다는 것을 알 수 있다.
이렇게 optional chaining과 optional binding에 대해서 알아봤는데...
여기 놓치기 쉬운 차이가 있다!
var river2 : Person = Person(name: "River",address: Address(city: "Busan", building: Building(name: "빌딩이름", room: Room(number: 1004))))
// 1) optional chaining 사용
var river2RoomNumber : Int? = river2.address?.building?.room?.number
// 2) optional binding 사용
if let address = river2.address{
if let building = address.building{
if let room : Int = building.room{
print(" room 번호 : \(room.number)")
}
}
}
optional chaining을 하면 optional 값으로 반환이 된다는 것이다.
앞서 말했던 것처럼 "number를 확인하기 이전의 단계에서 nil이라는 게 확인이 되면 뒤에꺼는 확인하지 않고 nil을 반환한다."
즉, nil 값이 들어갈 수 있는 것이다.
optional Binding과 optional Chaining 짬뽕
그래서 optional Binding과 optional Chaining 짬뽕시켜서 사용하는 게 일반적이다.
river2.address?.building?.room?.number( optional Chaining )를 통해 optional 값으로 number을 꺼내고,
if let( optional Binding )을 통해서 unwrapping을 해서 String 값으로 추출하는 것이다 !
var river2 : Person = Person(name: "River",address: Address(city: "Busan", building: Building(name: "빌딩이름", room: Room(number: 1004))))
if let room = river2.address?.building?.room?.number{
print(" room 번호 : \(room)")
}
+ ) guard let
if let과 비슷하게 unwrapping을 하는 guard let 을 마지막으로 알아보자 !
처음에는 if let과 guard let이 진짜 너무 헷갈렸는데, 쓰다보면 둘의 차이를 명확하게 알게 된다.
guard let 의 경우에는 swift 공문에 "Early Exit" title과 함께 나와있다.
말 그대로 nil인 경우에 빨리 해당 블록을 끝내는 거다.
그래서 하단의 코드를 보면, nil 일때 먼저 return을 하고,
만약에 nil이 아니라면, 기나긴 코드에서 _room 상수를 사용할 수 있고 마지막에 함수를 종료하게 된다.
var river2 : Person = Person(name: "River",address: Address(city: "Busan", building: Building(name: "빌딩이름", room: Room(number: 1004))))
func printRoomNumber(river : Person){
guard let _room = river.address?.building?.room?.number else{
print("nil 값")
return
}
// 기나긴 코드들
print(_room)
}
printRoomNumber(river : river2)
둘의 차이를 알아보자면, 다음과 같다.
if let | guard let |
A는 지역변수로만 사용 가능 → 블록 안에서만 A 사용 가능 | else 이후 블록 밖에서 쭉 A 사용 가능 |
조건문의 Optional 값이 nil인지 확인가능 | 조건문의 Optional 값이 nil인지 확인가능 guard let 구문은 먼저 else 를 통해 빨리 exit 시킴 1. 값이 있을 때 else 이후의 코드가 실행 2. 값이 없을 때 else 문이 실행되며, 상위 코드 블럭을 종료하는 함수인 continue, break return, throw 등이 반드시 필요 |
// 1) if let
if let A = B {
// B가 nil이 아닐때
// A 사용 가능
}else {
// B가 nil일 때
// A 사용 x
}
// A 사용 x
//2) guard let
guard let A = B else{
// B가 nil일 때
return
}
// B가 nil이 아닐때
// A 사용 가능
+ if let과 마찬가지로 quard let으로 unwrapping 할 때도 조건을 다는 것이 가능하다 !
optional을 처음 만났을 때 봤던,, "optional은 enum이다!" 와 관련해서 좋은 자료가 있어 덧붙이면,
forced unwrapping and optional binding
implicitly unwrapping optional
the Nil-Coalescing Operator
optional chaining
'오뚝이 개발자 > swift' 카테고리의 다른 글
struct와 class의 차이를 설명하시오. (0) | 2022.07.06 |
---|---|
removeLast() vs popLast() (0) | 2022.05.24 |
[1/2] Optional unwrapping (0) | 2022.05.14 |
Closure에서의 Capture ( feat . reference type) [2/3] (4) | 2022.05.11 |
Closure 넌 누구냐 ! [1/3] (0) | 2022.05.11 |