옵셔널
- 값이 있을 수도 없을 수도 있는 것
- 오직 옵셔널 타입만 nil을 반환할 수 있습니다.
- 오류의 발생 가능성이 조금이라도 있으면 옵셔널로 정의해 안정성을 높일 수 있습니다.
옵셔널 타입
- 옵셔널은 nil이거나 nil이 아닌 값만 가질 수 있습니다.
- nil : 실행 과정에서 오류가 발생했을 때
- nil이 아닌 값 : 오류가 발생하지 않았을 때, 반환하려는 값이 옵셔널 형태로 나오는 값
사용
- 자료형 뒤에 ?나 !를 붙여 옵셔널 타입으로 정의할 수 있습니다.
-? 나! 를 사용하여 옵셔널 객체 내부에 값이 대입되며, 값을 할당하지 않으면 자동으로 nil값이 됩니다.
옵셔널 해제
- 옵셔널 타입의 결괏값으로는 연산을 할 수 없습니다.
- 옵셔널 값으로 나온 결과는 반드시 옵셔널 언래핑을 해줘야 합니다.
- 옵셔널 해제는 명시적 해제와 묵시적 해제가 있습니다.
- 명시적 해제 : 강제 해제, 비강제 해제
- 묵시적 해제 : 컴파일러에 의한 자동 해제, ! 연산자를 통한 자동 해제
1, 강제 언래핑
- 옵셔널 타입의 값 뒤에 !를 사용해 일반 타입으로 강제 해제시킵니다.
- 반드시 옵셔널 값일 때만 사용해야 하며, 아닌 경우에 사용하면 오류가 발생합니다.
let Test: Int? = 10
print(Test) // Optional(10)
print(Test!) // 10
2, 옵셔널 바인딩
- 조건문을 통해 옵셔널 값을 일반 변수나 상수에 할당하는 방법입니다.
- if let이나 guard let을 통해 옵셔널 바인딩을 합니다.
let x : Int? = 10
let y : Int? = nil
if let xx = x {
print("x = \(xx)")
} else {
print("x is Optional")
}
if let yy = y {
print("y = \(yy)")
} else {
print("y is Optional")
}
// 출력 결과
// x = 10
// y is Optional
- 값이 있는 x는 xx에 초기화되어 if문을 수행하게 되어 옵셔널 값이 풀려 "x = 10"이 출력됩니다.
- 값이 nil인 y는 yy에 초기화되지 못해 옵셔널 바인딩이 되지 못하고 "y is Optional"이 출력됩니다.
let x : Int? = 10
let y : Int? = nil
func OptTest() {
guard let xx = x else {
return print("x is Optional")
}
print(xx)
guard let yy = y else {
return print("y is Optional")
}
print(yy)
}
OptTest()
// 출력 결과
// 10
// y is Optional
- guard let은 if문과 반대로 조건식이 거짓일 때의 값을 실행하는 것입니다.
- if let과 다르게 guard let을 통해 옵셔널 바인딩된 값은 함수 내에서 전역 변수로 사용할 수 있습니다.
- else 블록 안에는 return이나 throw와 같은 탈출 구문이 반드시 있어야 합니다.
3, 옵셔널 체이닝
- nil일수도 있는 프로퍼티나 메서드 그리고 서브 스크립트의 질의를 하는 과정입니다.
- 옵셔널이 프로퍼티나 메서드 그리고 서브 스크립트에 대한 값을 갖고 있다면 그 값을 반환하고 만약 값이 nil이면 nil을 반환합니다.
- 여러 질의를 연결해서 할 수 있으며, 연결된 질의 중 하나라도 nil이면 전체 결과는 nil이 됩니다.
클래스 생성
class Person {
var name: String
var job: String?
var home: Apartment? // nil
init(name: String) {
self.name = name
}
}
class Apartment {
var buildingNumber: String
var roomNumber: String
var man: Person? // nil
var owner: Person? // nil
init(dong: String, ho: String){
buildingNumber = dong
roomNumber = ho
}
}
인스턴스 생성
let SeaGreen: Person? = Person(name: "SeaGreen")
let apart: Apartment? = Apartment(dong: "101", ho: "101")
let superman: Person? = Person(name: "superman")
옵셔널 체이닝
- 연쇄적으로 프로퍼티에 값이 있는지 검사를 합니다.
func optionalChaining(owner: Person?){
if let guardJob = owner?.home?.man?.job {
print("아파트에 사는 남자의 직업은 \(guardJob)입니다.")
} else {
print("아파트에 사는 남자는 직업이 없습니다.")
}
}
optionalChaining(owner: SeaGreen)
옵셔널 체이닝 값 할당
- 옵셔널 체이닝을 통해 값을 불러오려 했을 때, nil값이 나오며 실행이 종료되었을 것입니다.
- 아래 코드를 통해 값을 할당하지 않았을 때, 어떤 결과가 출력될지 확인할 수 있습니다.
SeaGreen?.home?.man?.job // nil
SeaGreen?.home = apart
SeaGreen?.home // Optional(Apartment)
SeaGreen?.home?.man // nil
SeaGreen?.home?.man = superman
SeaGreen?.home?.man // Optional(Person)
SeaGreen?.home?.man?.name // superman
SeaGreen?.home?.man?.job // nil
SeaGreen?.home?.man?.job = "경비원"
4, nil 병합 연산자
- 옵셔널을 푸는 방법으로 nil 병합 연산자가 있습니다.
- 옵셔널 체이닝을 통해 옵셔널 값을 푸는 방법으로 ?? 앞의 값이 nil이라면 뒤의 작성된 코드를 실행하는 문법입니다.
- ?? 앞의 값이 옵셔널 값이라면 옵셔널이 풀어진 결과를 출력합니다.
var guardJob: String
guardJob = SeaGreen?.home?.man?.job ?? "슈퍼맨"
print(guardJob) // 경비원 출력
SeaGreen?.home?.man?.job = nil
guardJob = SeaGreen?.home?.man?.job ?? "슈퍼맨"
print(guardJob) // 슈퍼맨 출력
내용 출처 및 참고
'iOS > Swift 문법 복습' 카테고리의 다른 글
(인스턴스, 스태틱, 클래스) 메서드 (0) | 2022.06.30 |
---|---|
프로토콜 [Protocol] (0) | 2022.06.29 |
프로퍼티 (Properties) (0) | 2022.06.27 |
Struct와 Class, Enum의 차이를 설명하시오. (0) | 2022.06.25 |
댓글