이 글은 스위프트 프로그래밍(3판, 야곰 지음)을 읽고 간단하게 정리한 글입니다. 책에 친절한 설명과 관련 예제 코드들이 있으므로 직접 사서 읽기를 추천합니다.
옵셔널은 스위프트의 안전성을 문법으로 담보하는 기능이다. 뜻 그대로 "선택적인"이라는 뜻이며, 값이 있을 수도, 없을 수도 있음을 나타낸다. 옵셔널과 옵셔널이 아닌 값은 철저히 다른 타입으로 인식하게이 컴파일할 때 바로 오류를 걸러낼 수 있다.
값이 없음을 나타내는 nil은 옵셔널 변수 또는 상수에만 할당할 수 있다. 데이터 타입 뒤에 물음표(?)를 붙이거나 Optional<데이터타입>으로 표현한다. 옵셔널을 사용하는 경우들은 다음과 같다.
var name: String?
var name: Optional<String>
name = "name"
name = nil
열거형에서 rawValue로 접근하는 경우에는 타입이 Optional이다. rawValue에 해당하는 case가 있을 수도 있고 없을 수도 있기 때문이다.
enum School: String {
case primary = "유치원"
case highSchool
case graduate = "석박사"
}
let one = School(rawValue: "유치원") // primary
let two = School(rawValue: "고등학교") // nil
let three = School(rawValue: "highSchool") // highSchool
let four = School.graduate // graduate
type(of: one) // Optional
type(of: two) // Optional
type(of: three) // Optional
type(of: four) // School
옵셔널은 제네릭이 적용된 열거형이다. ExpressibleByNilLiteral 프로토콜도 따른다.
*제네릭(Generic): 포괄적인 이라는 의미이다. 타입에 유연하게 대처할 수 있다.
*ExpressibleByNilLiteral: nil로 초기화 될 수 있는 타입 조건을 나타낸다.
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
public init(_ some: Wrapped)
...
}
열거형의 some 케이스의 값을 옵셔널이 아닌 값으로 추출하는 방법이다.
말 그대로 강제로 추출하는 것으로 런타임 오류가 일어날 가능성이 높다.
var name: String?
name = nil
name! // 런타임 에러
name = "Lee"
name! // name
옵셔널에 값이 있는지 확인할 때 if나 while구문 등과 결합하여 사용한다. 값이 있다면 그 값을 일정 블록 안에서 사용할 수 있는 상수나 변수에 할당해 사용한다.
name이라는 임시 상수를 사용해서 if 블록 내에서 사용하였다. 그렇기에 name이라는 이름이 중복되었지만 충돌이 일어나지 않았다. 한번에 여러 값들을 추출할수도 있다..
var name: String?
if let name = name {
print("name == \(name)"))
} else {
print("name == nil")
}
// name == nil
var name: String?
var age: Int?
name = "Lee"
age = 1
if let name = name, let age = age {
print("name == \(name) or age == \(age)")
} else {
print("name == nil or age == nil")
}
// name == Lee or age == 1
로직상 nil이 아닐 것 같은 위험한? 확신이 들 때 암시적 추출 옵셔널을 사용한다. 타입 뒤에 느낌표(!)를 붙인다. 추천하지 않는다. 그냥 안전하게 쓰자.
var name: String! = "Lee"
if let name = name {
print("name == \(name)")
} else {
print("name == nil")
}
// name == Lee
name = nil
name.isEmpty // 런타임 에러