일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Xib
- 스프링
- 딩동말씀
- 앱배포
- 개발기록
- customclass
- Xcode
- FLASK
- 파이썬서버
- AJAX
- 자바스크립트
- MainScheduler
- iOS앱배포
- 계산기앱만들기
- DispatchGroup
- 앱버전구하기
- Python
- 스위프트
- 웹
- subscript
- iOS배포
- 맥
- 계산기앱
- ios
- spring
- Swift
- FileOwner
- JavaScript
- iOS계산기
- jQuery
- Today
- Total
개발하는 뚝딱이
[swift] 옵셔널 체이닝과 빠른 종료 본문
책 <스위프트 프로그래밍 3판 ;야곰 지음> 을 정리한 글입니다.
1. 옵셔널 체이닝
- Optional Chaining
- 옵셔널에 속해 있는 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
}
}
- Eric 인스턴스와 옵셔널 체이닝
let eric: Person = Person(name: "Eric")
let ericRoomViaOptionalChaining: Int? = eric.address?.building?.room?.number // nil
let ericRoomViaOptionalUnwrapping: Int = eric.address!.building!.room!.number // 오류 발생
- 옵셔널 바인딩과 옵셔널 체이닝 비교
// 옵셔널 바인딩
let eric: Person = Person(name: "Eric")
var roomNumber: Int? = nil
if let ericAddress = eric.address {
if let ericBuilding = ericAddress.building {
if let ericRoom = ericBuilding.room {
roomNumber = ericRoom.number
}
}
}
if let number: Int = roomNumber {
print(number)
} else {
print("Can not find room number")
}
// 옵셔널 체이닝
let eric: Person = Person(name: "Eric")
if let roomNumber: Int = eric.address?.building?.room?.number {
print(roomNumber)
} else {
print("Can not find the room number")
}
- 옵셔널 체이닝을 통한 값 할당
- 상위 프로퍼티의 값이 없으면 nil을 반환하며, 체이닝이 도중에 중지됨
eric.address?.building?.room?.number = 505
print(eric.address?.building?.room?.number) // nil
eric.address = Address(province: "서울시", city: "중구", street: "을지로", building: nil, detailAddress: nil)
eric.address?.building = Building(name: "빌딩1")
eric.address?.building?.room = Room(number: 0)
eric.address?.building?.room?.number = 505
print(eric.address?.building?.room?.number) // Optional(505)
- 옵셔널 체이닝을 통한 서브스크립트 호출
- 옵셔널의 서브스크립트를 사용할 때, 프로퍼티 이름과 대괄호([) 사이에 물음표(?)를 표기해줘야 함
let optionalArray: [Int]? = [1, 2, 3]
optionalArray?[1] // 2
var optionalDictionary: [String: [Int]]? = [String: [Int]]()
optionalDictionary?["numberArray"] = optionalArray
optionalDictionary?["numberArray"]?[2]
2. 빠른 종료
- Early Exit
- guard 구문을 이용하며, if 구문과 유사하게 Bool 타입의 값으로 동작
- guard 뒤에 따라붙는 코드의 실행 결과가 true일 때 코드가 계속 실행됨
- guard 구문 뒤에는 항상 else 구문이 뒤에 따라와야 하며, 꼭 자신보다 상위의 코드 블록을 종료하는 코드가 들어가야 함
- 그래서 특정 조건에 부합하지 않다는 판단이 되면 재빠르게 코드 블록을 종료할 수 있음
- 현재의 코드 블록을 종료할 때는 return, break, continue, throw 등의 제어문 전환 명령 사용
- fatalError()와 같은 비반환 함수나 메서드를 호출할 수 있음
비반환함수
- 종료되지 않는 함수, 정상적으로 끝나지 않는 함수
- 비반환 함수가 실행되면 프로세스가 죽어버림
- 재정의는 가능하지만 비반환 타입은 변경할 수 없음
- 리턴 타입은 Never
- if 구문과 guard 구문의 비교
// if 구문을 사용한 코드
for i in 0...3 {
if i == 2 {
print(i)
} else {
continue
}
}
// guard 구문을 사용한 코드
for i in 0...3 {
guard i == 2 else {
continue
}
print(i)
}
- 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 near you")
return
}
print("I hope the weather is nice in \(location)")
}
var personInfo: [String: String] = [String: String]()
personInfo["name"] = "Jenny"
greet(personInfo) // Hello Jenny!
// I hope the weather is nice near you
personInfo["location"] = "Korea"
greet(personInfo) // Hello Jenny
// I hope the weather is nice in Korea
- 조금 더 구체적인 조건을 추가하고 싶다면 쉼표(,)로 추가조건을 나열해주면 됨
- 추가된 조건은 Bool 타입 값이어야 함
- 또 쉼표(또는 &&)로 추가된 조건은 AND 논리연산과 같은 결과를 줌
func enterClub(name: String?, age: Int?) {
guard let name: String = name, let age: Int = age, age > 19, name.isEmpty == false else {
print("You are too young to enter the club")
return
}
print("Welcome \(name)!")
}
- guard 구문의 한계는 자신을 감싸는 코드 블록의 제어문 전환 명령어를 쓸 수 없는 상황이라면 사용이 불가능
- 함수나 메서드, 반복문 등 특정 블록 내부에 위치하지 않는다면 사용이 제한됨
let first: Int = 3
let second: Int = 5
guard first > second else {
// 여기에 들어올 제어문 전환 명령이 딱히 없음
// 오류!
}
'swift' 카테고리의 다른 글
[swift] 타입캐스팅 (0) | 2020.05.17 |
---|---|
[swift] 맵, 필터, 리듀스 (0) | 2020.05.13 |
[swift] 클로저 (0) | 2020.05.07 |
[swift] 접근제어 (0) | 2020.05.02 |
[swift] 인스턴스 생성 및 소멸 (0) | 2020.05.01 |