Optional은 nil을 사용할 수 있는 타입과 없는 타입을 구분하기 위함이며, nil을 사용할 수 있는 Type을 Optional Type이라 부른다
옵셔널 타입은 기존 자료형을 Optional로 한번 감싼 Type
nil은 포인터가 아니라 특정 타입에 대한 값의 부재를 나타냄
0이나 공백이 아닌 값의 부재를 표현
enum Optional<T> { // <T> 는 Array<T>같은 일반적인 타입
case None
case Some(T) //T의 의미는 옵셔널이 모든타입의 옵셔널이 될 수 있다는 뜻
}
let x: String ? = nill
// 는 아래와 동일
let x = Optional<String>.None
let x: String ? = "hello"
// 는 아래와 동일
let x = Optional<String>.Some("hello")
var y = x!
// 는 아래와 동일
switch x{
case Some(let value): y = value
case None: //예외 발생
}
let x: String? = ...
if let y = x{
// do something with y
}
// 는 아래와 동일
switch x {
case .Some(let y):
// do something with y
case .None:
break
}
var display: UILabel?
if let label = display{
if let text = label.text{
let x = text.hashValue
...
}
}
// 아래와 동일
if let x = display?.text?.hashValue {...}
let s: String? = ...
if s != nill{
display.text = s
} else {
display.text = " "
}
// 아래와 동일
display.text = s ?? " "
옵셔널 타입은 기존 자료형을 Optional로 한번 감싼 Type
옵셔널 타입에 저장된 값을 사용하기 위해서는 Optional을 벗겨줘야 하고 이 작업을 Optional Unwrapping 이라고 한다.
let a: Int?
a = 4
print(\(a)) // Optional(4) 출력, Optional Unwrapping 가능
let b: Int? = nil
print(\(b)) // nil 출력, Optional을 벗길 수 없음
옵셔널 값이 nil이건 말건 옵셔널을 벗겨버리는 것
Optional로 선언된 변수(상수) 뒤에 !를 붙여줌
let a: Int?
a = 4
print(\(a!)) // 4 출력
let b: int? = nil
print(\(b!)) //에러
안전하게 Optional의 값을 Unwrapping 하는 방법
let optionalNum: Int? = 4
if let nonOptionalNum = optionalNum {
//optionalNum이 nil이 아닐경우 Unwrapping하여 그 값을 nonOptionalNum에 대입
//nonOptionalNum은 해당 if문 안에서만 접근 가능
print(nonOptionalNum) // 4 출력
print(optionalNum) // Optional(4)출력
}else{
print(optionalNum)//optionalNum이 nil일경우
}
let num: Int? = 4
if let num = num {
print(num)
}
let name: String? = nil
let age: Int? = nil
if let name = name, let age = age{
// name != nil && age != nil 일 경우
}
if let name = name, let age = age, age > 5{
// name != nil && age != nil && age >5 일 경우
}
guard문은 특성상 함수(메서드)에서만 쓰이며, guard 구문의 조건을 만족하지 못하면 else문으로 빠져서 함수의 실행을 종료 시킬 때 사용
guard let nonOptionalNum = optionalNum else{
// optionalNum이 nil일 경우
// nonOptionalNum 값 사용 불가
return
}
//optionalNum이 nil이 아닐경우
// nonOptionalNum값 사용가능
func test(_ name: String?) {
guard let name = name else {
return
}
print(name)
}
func test() {
let num: Int? = 4
guard let num = num else{// 에러 사용불가
return
}
}
func test(_ name: String?, _ age: Int?) {
guard let name = name, let age = age, age < 5 else {
return
}
}

Implicitly Unwrapped Optional(옵셔널 암시적 추출)은 Optional Type으로 선언하는 방법 중 하나로 Non-Optional Type으로 처리되어야 할 때 값을 자동으로 추출해 줌(특정 조전일 때만 추출)
//기존 Optional Type
var num: Int? = 4
var num2: Int = num //에러
//IUO(Implicitly Unwrapped Optional)
var num: Int! = 4
var num2: Int = num //가능
var num: Int! = nil
var num2: Int = num // 에러
??연산자를 통하여 옵셔널 바인딩을 간단히 할 수 있다.
Optional Type에 값이 있을 경우 해당 값을 아닐경우 ??연산자 뒤의 값을 return
Optional Expression ?? Non-Optional Expression
기존)
if let name = name {
print("hello, \(name)")
} else {
print("hello, what's your name?")
}
??연산자 사용)
print("hello, "+(name ?? "what's your name?"))
옵셔널을 연쇄적으로 사용하는 것
.(dot)을 통해 내부 프로퍼티나 메서드에 연속적으로 접근할 때 옵셔널 값이 하나라도 껴 있을 경우 옵셔널 체이닝이라고 함
person.contacts?.address // 하나라도 nil일 경우 nil 반환
person?.contacts?.address // 하나라도 nil일 경우 nil 반환
sturct Person {
var name: String
var contacts: Contacts
init(name: String, email: String, address: String){
self.name = name
contacts = Contacts(email: email, address: ["home" : address])
}
func getContacts() -> Contacts?{
return contacts
}
func getContacts2() -> Contacts2{
return contacts
}
}
person?.getContacts()?.email // 함수의 리턴값의 속성에 접근할 때
let function = person?.getContacts2 // function은 Optional Type
function?().email // 함수 자체가 옵셔널일 경우
let function2 = person?.getContacts // funtion은 Optional Type
function?()?.email // 함수 자체도 옵셔널, 리턴 값도 옵셔널 일 경우
let dic: [String : String] = ["name" : "abc"]
dic["name"]?.count
let dic: [String : String]? = ["name" : "abc"]
dic?["name"]?.count
참조
개발자 소들이