옵셔널
- 스위프트의 안전성을 문법으로 담보하는 기능이다.
- 옵셔널(optional)이란 사전적 의미는 '선택적인', 즉 값이 '있을 수도, 없을 수도 있음'을 나타내는 표현이다.
- 즉 '변수나 상수 등에 꼭 값이 있다는 것을 보장할 수 없다. 즉, 변수 또는 상수의 값이 nil일 수도 있다.'는 의미
- 옵셔널과 옵셔널이 아닌 값은 철저히 다른 타입으로 인식하기 때문에 컴파일할 때 오류를 걸러낼 수 있다.
1. 옵셔널 사용
- '?'를 붙여 표현할 수 있다.
- 옵셔널 변수 또는 상수가 아니면 nil을 할당 할 수 없다.
- nil이란?
- Int 타입의 변수에 0을 할당했다면 값이 없다는 의미가 아니라 '0'이라는 '값'을 넣을 것이다. " "로 빈 문자열을 만들었다면 이 또한 '빈 문자열'이라는 값을 의미하지, 값이 없음을 나타내는 것은 아니다. nil을 정말로 값이 없을 때만 사용한다.
- 해당 변수 또는 상수에는 값이 없을 수 도 있다. 즉, 변수 또는 상수가 nil일 수도 있으므로 사용에 주의하라로 해석하면 된다.
- 값이 없는 옵셔널 변수 또는 상수에 접근하려면 런타임 오류가 발생한다.
- 옵셔널을 사용하는 상황
- 함수의 전달인자 값이 잘못 된 경우, 제대로 처리 못했음을 nil을 반환하여 표현한다.
var myname: String = "Jin"
myName = nil
var myName: String? = "Jin"
print(myName)
myName = nil
print(myName)
- 옵셔널 자체가 열거형이기에 옵셔널 변수는 switch 구문을 통해 값이 있고 없음을 확인할 수 있다.
func checkOptionalValue(value optionalValue: Any?){
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
}
var myName: String? = "Jin"
checkOptionalValue(value: myName)
myName = nil
checkOptionalValue(value: myName)
let numbers: [Int?] = [2, nil, -4, nil, 100]
for number in numbers {
switch number {
case .some(let value) where value < 0:
print("Negative value!! \(value)")
case .some(let value) where value > 10:
print("Large value!! \(value)")
case .some(let value):
print("value \(value)")
case .none:
print("nil")
}
}
2. 옵셔널 추출
- 열거형의 some 케이스로 숨어있는 옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 옵셔널 추천(Optional Unwrapping)
2.1. 강제 추출
- 옵셔널 값의 뒤에 느낌표(!)를 붙여주면 된다.
- 옵셔널 값을 추출하는 가장 간단하지만 가장 위험한 방법이다.
- 런타임 오류가 일어날 가능성이 가장 높기 때문이다.
- 옵셔널을 만든 의미가 무색해지는 방법이다.
- 강제 추출시 옵셔널에 값이 없다면, 즉 nil이라면 런타임 오류가 발생한다.
- 런타임 오류의 가능성을 늘 가지고 있기에 강제 추출 방식은 지양해야한다.
var myName: String? = "Jin"
var Jin: String = myName!
myName = nil
Jin = myName!
if myName != nil {
print("My name is \(myName!)")
} else {
print("myName == nil")
}
2.2. 옵셔널 바인딩
- if 또는 while 구문 등과 결합하여 사용가능하다.
- 옵셔널에 값이 있는지 확인할 때 사용한다.
- 만약 옵셔널 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있게 해준다.
var myName: String? = "Jin"
if let name = myName {
print("My name is \(name)")
} else {
print("myName == nil")
}
if var name = myName {
name = "wizplan"
print("My name is \(name)")
} else {
print("myName == nil")
}
2.3. 암시적 추출 옵셔널
- 옵셔널은 물음표(?)를 사용했지만 암시적 추출 옵셔널은 느낌표(!)를 사용하면 된다.
- 때때로 nil을 할당하고 싶지만, 옵셔널 바인딩으로 추출하기 귀찮거나 로직상 nil때문에 런타임 오류가 발생하지 않는다는 확신이 들 때 사용한다.
var myName: String! = "Jin"
print(myName)
myName = nil
if let name = myName {
print("My name is \(name)")
} else {
print("myName == nil")
}
myName.isEmpty