티스토리 뷰
옵셔널 체이닝은 nil일 수도 있는 프로퍼티나, 메서드 그리고 서브스크립트에 질의를 하는 과정을 말한다.
만약 옵셔널이 프로퍼티나 메소드 혹은 서브스크립트에 대한 값을 갖고 있다면, 그 값을 반환하고 값이 nil이면 nil을 반환한다.
이전에 처음 옵셔널이라는 개념을 공부하면서 슬쩍 접했던 내용이기는 하다.
그 문법과 활용을 자세히 알아보도록 하자.
1. 강제 언래핑의 대체로써의 옵셔널 체이닝
옵셔널 체이닝은 옵셔널 값 뒤에 물음표를 붙여 표현이 가능하다. 옵셔널 값을 강제 언래핑 하기 위해서는 뒤에 느낌표를 붙이는 것과 문법이 비슷하지만, 언래핑을 !로 했는데 만약 그 값이 nil 이라면 런타임 에러를 발생시키지만, 옵셔널 체이닝을 활용하면 런타임 에러 대신 nil이 반환 된다는 것이다.
아래 예제는 옵셔널 체이닝과 강제 언래핑이 어떻게 다른 지 확인할 수 있는 예제이다.
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
///// 강제 언래핑 /////
let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error
///// 옵셔널 체이닝 /////
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."
2. 옵셔널 체이닝을 위한 모델 클래스 정의
옵셔널 체이닝을 프로퍼티, 메서드 그리고 서브스크립트에서도 사용할 수 있는데, 한 단계가 아닌 여러 level로 multilevel optional chaining 을 사용할 수 있다.
이번에는 위 예제를 확장하여 Room과 Address 클래스를 추가한 4가지 모델을 정의해보자.
class Person {
var residence: Residence?
}
class Residence {
var rooms = [Room]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
get {
return rooms[i]
}
set {
rooms[i] = newValue
}
}
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}
Residence 클래스는 이전 보다 조금 더 복잡하게 빈 Room 배열과 배열 엘리먼트를 set, get 할 서브스크립트와 메서드를 추가했다.
그리고 아래에 클래스 이름 하나를 인자로 받아 초기화 하는 Room 객체와 3개의 String? 옵셔널 프로퍼티를 갖는 Address가 추가됐다.
class Room {
let name: String
init(name: String) { self.name = name}
}
class Address {
var buildingName: String?
var buildingNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if let buildingName = buildingName, let street = street {
return "\(buildingName) \(street)"
} else if buildingName != nil {
return buildingName
} else {
return nil
}
}
}
- 옵셔널 체이닝을 통한 프로퍼티 접근
이제 옵셔널 체이닝을 이용하여 위 클래스들의 프로퍼티에 접근할 수 있다.
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s)")
} else {
print("Unable to retrieve the number of rooms.")
}
let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
john.residence?.address = someAddress
위 코드의 경우 john 이라는 Person 인스턴스의 프로퍼티인 residence가 그 어디에도 할당되지 않았기 때문에 nil이며, someAddress 할당도 실패하지만 에러는 나지 않는다.
func createAddress() -> Address {
print("Function was called")
let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
return someAddress
}
john.residence?.address = createAddress()
위 코드를 실행하면, Function was called 구문이 아예 출력이 되지 않는다. john.residence? 가 nil 이기 때문에 할당에 실패하며, 그럼 우변 또한 실행이 되지 않기 때문이다.
- 옵셔널 체이닝을 통한 메서드 호출
마찬가지로 옵셔널 체이닝을 이용한 메서드 호출 또한 가능하다.
위 residence 클래스의 printNumberOfRooms() 메서드의 반환 타입이 nil 인지 판단하여 다른 출력 값을 내보내는 예제이다.
if john.residence?.printNumberOfRooms() != nil {
print("It was possible to print the number of rooms.")
} else {
print("It was not possible to print the number of rooms.")
}
// Prints "It was not possible to print the number of rooms."
if (john.residence?.address = someAddress) != nil {
print("It was possible to set the address.")
} else {
print("It was not possible to set the address.")
}
// Prints "It was not possible to set the address."
- 옵셔널 체이닝을 이용한 서브스크립트 접근
같은 맥락이다. 옵셔널 체이닝에 [] 을 붙여 서브스크립트를 호출할 수 있다.
if let firstRoomName = john.residence?[0].name {
print("The first room name is \(firstRoomName).")
} else {
print("Unable to retrieve the first room name.")
}
// Prints "Unable to retrieve the first room name."
위 예제는 마찬가지로 resience가 nil이기 때문에 할당에 실패한다.
residence 인스턴스를 아래와 같이 할당해준다면, residence 서브스크립트를 사용할 수 있다.
let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "Living Room"))
johnsHouse.rooms.append(Room(name: "Kitchen"))
john.residence = johnsHouse
if let firstRoomName = john.residence?[0].name {
print("The first room name is \(firstRoomName).")
} else {
print("Unable to retrieve the first room name.")
}
// Prints "The first room name is Living Room."
'Mobile > ios' 카테고리의 다른 글
[ios] swift 기본 문법 정리 17: Type Casting (0) | 2022.12.08 |
---|---|
[ios] swift 기본 문법 정리 16: Error Handling (0) | 2022.12.08 |
[ios] swift 기본 문법 정리 14: DeInitialization (0) | 2022.12.07 |
[ios] swift 기본 문법 정리 13: Initialization (0) | 2022.12.07 |
[ios] swift 기본 문법 정리 12: Inheritance (0) | 2022.12.06 |
- 파니노구스토
- javascript
- 인천 구월동 맛집
- Promise
- Async
- 인천 구월동 이탈리안 맛집
- react-native
- 정보보안기사 #실기 #정리
- redux
- react
- await
- 이탈리안 레스토랑
- redux-thunk
- 맛집
- AsyncStorage
- Total
- Today
- Yesterday