1️⃣ 옵셔널 체이닝?
- 옵셔널에 속해있는 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
}
}
// yejin 인스턴스 생성
let yejin: Person = Person(name: "yejin")
// 옵셔널 체이닝 문법
// yejin이 사는 호실 번호를 알아보기
let yejinRoomViaOptionalChaining: Int? = yejin.address?.building?.room?.number // nil
let yejinRoomViaOptionalUnwrapping: Int = yejin.address!.building!.room!.number // 오류 발생
옵셔널 바인딩을 사용하지 않고 옵셔널 체이닝을 사용하여 yejin이 사는 호실 정보를 가져오는 코드
// yejin 인스턴스 생성
let yejin: Person = Person(name: "yejin")
// 옵셔널 체이닝
if let roomNumber: Int = yejin.address?.building?.room?.number{
print(roomNumber)
} else {
print("Can not find room number")
}
-> yejin의 address가 nil이기 때문에 더 이상 다음 체인의 building을 체크하지 않고 nil을 반환한다.
옵셔널 체이닝을 통한 값 할당 시도
yejin.address?.building?.room?.number = 404
print(yejin.address?.building?.room?.number) // nil
아직 yejin의 프로퍼티에 address, building, room 프로퍼티 모두 없다. 그렇기 때문에 옵셔널 체이닝은 동작 도중 중지될 것이다.
number 프로퍼티는 존재조차 하지 않아서 404가 할당되지 않는다.
옵셔널 체이닝을 통한 메서드 호출
(Address 구조체에 메서드 코드를 추가하고 옵셔널 체인을 통해 호출)
struct Address {
var province: String // 광역시/도
var city: String // 시/군/구
var street: String
var building: Building?
var detailAddress: String?
init(province: String, city: String, street: String){
self.province = province
self.city = city
self.street = street
}
func fullAddress() -> String? {
var restAddress: String? = nil
if let buildingInfo: Building = self.building {
restAddress = buildingInfo.name
} else if let detail = self.detailAddress {
restAddress = detail
}
if let rest: String = restAddress {
var fullAddress: String = self.province
fullAddress += " " + self.city
fullAddress += " " + self.street
fullAddress += " " + rest
return fullAddress
} else {
return nil
}
}
func printAddress() {
if let address: String = self.fullAddress(){
print(address)
}
}
yejin.address?.fullAddress()?.isEmpty // false
yejin.address?.printAddress()
옵셔널 체이닝을 통한 서브스크립트 호출
let optionalArray: [Int]? = [1,2,3]
optionalArray?[1] // 2
var optionalDictionary: [String: [Int]]? = [String: [Int]]()
optionalDictionary?["numberArray"] = optionalArray
optionalDictionary?["numberArray"]?[2] // 3
2️⃣ 빠른 종료
💡guard 키워드
guard Bool 타입 값 else {
예외사항 실행문
제어문 전환 명령어
}
- if 구문을 사용하면 예외사항을 else 블록으로 처리해야하지만 예외사항만 처리하고 싶다면 guard 구문을 사용하는 것이 편리!
guard 구문의 옵셔널 바인딩 활용
- guard 뒤에 따라오는 옵셔널 바인딩 표현에서 옵셔널의 값이 있는 상태라면 guard 구문에서 옵셔널 바인딩된 상수를 guard 구문이 실행된 아래 코드부터 함수 내부의 지역상수처럼 사용할 수 있다.
func greet(_ person: [String: String]){
guard let name: String = person["name"] else {
return
}
print("Hello \(name)")
guard let location: String = person["location"] else {
print("I hope the weather is nice to near you")
return
}
print("I hope the weather is nice in \(location)")
}
var personInfo: [String: String] = [String: String]()
personInfo["name"] = "yejin"
greet(personInfo)
// Hello yejin
// I hope the weather is nice to near you
💡assert 키워드
- assert 함수는 디버깅 모드에서만 사용가능 (배포하는 애플리케이션에서는 제외)
- 주로 디버깅 중, 조건의 검증을 위해 사용된다.
- 조건문을 확인하고 충족할 시에는 아래의 코드 계속 실행, 미 충족 시에는 미충족 메시지 출력 후 종료
assert (_:_:file:line)
→ 체크할 조건문 : 조건 미충족 시 메시지 : 메시지를 출력할 파일 : 출력할 메시지 라인 수
import Foundation
// 조건 충족
var Info: Int = 0
assert(Info == 0, "Info != 0")
Info = 1
print(Info)
/// 1
// 조건 미충족
assert(Info == 0, "Info != 1")
Info = 2
print(Info)
/// Assertion failed: Info != 1
Reference
Swift 스위프트 프로그래밍 - 야곰
'Swift' 카테고리의 다른 글
[Swift] 모나드 : 컨텍스트, 함수객체, 모나드 (0) | 2022.03.24 |
---|---|
[Swift] 맵, 필터, 리듀스 (0) | 2022.03.22 |
[Swift] 클로저 : Closure (0) | 2022.03.20 |
[Swift] 접근제어 : 읽기 전용 구현 (0) | 2022.03.19 |
[Swift] 함수를 사용한 프로퍼티 기본값 설정 (0) | 2022.03.19 |