swift 기본문법 - 옵셔널체이닝과 nil 병합 연산자(optional chaining & nil-coalescing operator)
16 Jan 2020 | swift개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
인프런, 야곰의 스위프트 기본문법 강좌를 듣고 정리하였습니다.
옵셔널 체이닝(optional chaining)
구조체, 클래스등을 선언해줄때 구조체 안에 또다른 구조체 인스턴스가 들어올 수 있는데, 이렇게 연결되어 프로퍼티를 타고타고 들어가는 경우가 생긴다.
이 프로퍼티 자체가 옵셔널인 경우에는 이게 nil인지 아닌지를 확인해야하는 경우가 있다.
즉, 옵셔널 요소 내부의 프로퍼티로 또다시 옵셔널이 연속적으로 연결되는 경우 유용하게 사용할 수 있다.
class Person {
var name: String
var job: String?
var home: Apartment?
init(name: String) {
self.name = name
}
}
class Apartment {
var buildingNumber: String
var roomNumber: String
var `guard`: Person?
var owner: Person?
init(dong: String, ho: String) {
buildingNumber = dong,
roomNumber = ho
}
}
let zehye: Person? = Person(name: "zehye")
let apart: Apartment? = Apartment(dong: 101, ho: 3)
let superman: Person? = Person(name: "superman")
세개의 인스턴스를 생성했고 이때 생성만 하고 안에있는 프로퍼티들은 모두 nil 상태이다. > 옵셔널이 초기화됐을때 nil이 할당되어있기 때문
이때 가지게 되는것은 꼭 필요했던 프로퍼티 값들만 가지고 있다 (name, dong, ho)
옵셔널 체이닝을 사용하지않고 경비원의 직업이 궁금하다면?
func guardJob(owner: Person?) {
if let owner = owner {
if let home = home {
if let `guard` = home.guard {
if let guardJob = `guard`.job {
print("우리집 경비원의 직업은 \(guardJob)입니다")
} else {
print("우리집 경비원은 직업이 없어요")
}
}
}
}
}
이렇듯 엄청 복잡하다. 이때 옵셔널 체이닝을 사용해보자!
func guardJobOptionalChaining(owner: Person?) {
if let guardJob = owner?.home?.guard?.job {
print("우리집 경비원의 직업은 \(guardJob)입니다")
} else {
print("우리집 경비원은 직업이 없어요")
}
}
guardJobOptionalChaining(owner: zehye)
zehye?.home?.guard?.job // nil
zehye?.home = apart
zehye?.home // Optional(Apartment)
zehye?.home?.guard // nil
zehye?.home?.guard = superman
zehye?.home?.guard // Optional(Person)
zehye?.home?.guard?.name // superman
zehye?.home?.guard?.job // nil
zehye?.home?.guard?.job = "경비원"
zehye?.home?.guard?.job // 경비원
nil 병합 연산자 (nil-coalescing operator)
옵셔널 체이닝을 사용하면 값이 할당되지 않은 애들은 무조건 nil을 반환하게 되는데, nil이 아닌 기본값을 설정하고 싶다면 nil 병합 연산자를 사용해준다.
이는 ??
을 사용하는 것으로 ?? 앞의 값이 nil이라면 ?? 이후 값을 반환해달라 라는 의미이다.
var guardJob: String
guardJob = zehye?.home?.guard?.job ?? "슈퍼맨"
print(guardJob) // 경비원
zehye?.home?.guard?.job = nil
guardJob = zehye?.home?.guard?.job ?? "슈퍼맨"
print(guardJob) // 슈퍼맨