swift의 특징 중 하나인 안전성을 문법으로 담보하는 기능입니다.
옵셔널은 단어 뜻 그대로 '선택적인' 즉, 값이 있을 수도 없을 수도 있음을 나타내는 표현입니다.
nil 키워드를 이용해서 사용합니다.
- optional은 optional 상수 혹은 변수에만 사용할 수 있습니다.
- 즉, 변수 또는 상수가 nil일수도 있으므로, 사용에 조심해라라는 뜻으로 받아드릴 수 있습니다.
- 옵셔널 변수 또는 상수는 물음표 (?) 를 붙혀 사용합니다.
var myName: String? // optional 변수 선언
myName = "Lumi" // String 변수처럼 사용할 수 있습니다.
print(myName) // 실행결과 : Optional("Lumi")
myName = nil // nil 키워드를 사용할 수 있습니다.
print(myName) // 실행결과 : nil
옵셔널을 사용하는 상황
- 간단히 nil을 반환하여, 오류처리를 할 수 있습니다.
- 옵셔널이 매개변수라면, 매개변수를 굳이 넘기지 않아도 되는 구나, 하고 이해할 수 있습니다.
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
public init(_ some: Wrapped)
// 중략
}
옵셔널이 값을 갖는 케이스와 그렇지 못한 케이스 두가지로 정의되어 있습니다.
옵셔널 자체가 열거형임을 알 수 있습니다.
func isOptional(value: Any?) {
switch value {
case .none:
print("This Optional value is nil")
case .some(let value):
print("Value is \(value)")
}
}
var myName: String? = "Lumi"
isOptional(value: myName)
// 실행결과 : Value is Lumi
myName = nil
isOptional(value: myName)
// 실행결과 : This Optional value is nil
옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 옵셔널 추출 방법이 있습니다.
- 강제추출
- 옵셔널 바인딩
- 암시적 추출 옵셔널
강제추출은 가장 간단하지만, 가장 위험한 방법입니다.
런타입 오류가 일어날 확률이 가장 높기 때문입니다.
옵셔널의 값을 강제 추출하려면 옵셔널 값의 뒤에 느낌표(!)를 붙여줍니다.
- 만약 강제 추출 시 옵셔널에 값이 없다면, 런타입 오류가 발생합니다.
var myName: String? = "Lumi"
// 옵셔널 변수를 String 변수에 바로 할당할 수 없습니다.
var lumi: String = myName!
myName = nil
//lumi = myName! : 런타입 에러 발생
myName = "Lumi"
// if문을 통해 조금 더 안전하게 처리해볼 수 있습니다.
if myName != nil {
lumi = myName!
print("My name is \(lumi)!")
} else {
print("myName is nil")
}
옵셔널 바인딩은 옵셔널에 값이 있는지 확인할 때, 사용합니다.
만약 옵셔널에 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있도록 해줍니다.
- 옵셔널 바인딩은 if 또는 While 구문 등과 결합하여 사용할 수 있습니다.
var myName: String? = "Lumi"
var lumi: String
if let name = myName {
lumi = name
print("My name is \(lumi)")
} else {
print("myName is nil")
}
// 실행결과 : My name is Lumi
myName = nil
if let name = myName {
lumi = name
print("My name is \(lumi)")
} else {
print("myName is nil")
}
// 실행결과 : myName is nil
위의 예제에서는 if 구문을 실행하는 블로 안쪽에서만 name이라는 임시 싱수를 사용할 수 있습니다.
var myName: String? = "Lumi"
var yourName: String? = nil
if let name = myName, let girlFriend = yourName {
print("I'm \(name), I love you \(girlFriend) ")
}
// yourName이 nil임으로 임시 변수에 할당 되지 않습니다.
yourName = "Jogyul"
if let name = myName, let girlFriend = yourName {
print("I'm \(name), I love you \(girlFriend) ")
}
// 실행결과 : I'm Lumi, I love you Jogyul
때때로 nil을 할당하고 싶지만, 옵셔널 바인딩으로 매번 값을 추출하기 귀찮거나 로직상 nil 때문에 런타임 오류가 발생하지 않을 것 같다는 확신이 있을 때, nil을 할당해줄 수 있는 옵셔널이 아닌 변수나 상수가 필요합니다.
암시적 추출 옵셔널을 사용하려면 타입 뒤에 느낌표(!)를 사용해주면 됩니다.
var myName: String! = "Lumi"
print(myName)
myName = nil
// 암시적 추출 옵셔널도 옵셔널이므로 당연히 바인딩을 사용할 수 있습니다.
if let name = myName {
print("My name is \(name) !")
} else {
print("myName is nil")
}