옵셔널(Optional)이란 nil을 사용할 수 있는 타입으로, 옵셔널 타입(Optional Type)이라 부른다.
옵셔널은 Type casting이나 nil value 체크 등에 있어 Swift의 안전한 코딩을 도와주는 언어입니다.
옵셔널을 해제하는 방법은 명시적 해제 와 묵시적 해제가 있고, 명시적 해제 에는 강제해제
와 비강제 해제
, 묵시적 해제는 컴파일러에 의한 자동해제
, !연산자를 이용한 자동 해제
로 나눌 수 있다.
!를 붙이면 강제해제된다. 단 강제해제는 위험하므로 nil이 아닐 때를 점검하는 것이 좋다.
var str = "123"
var intFromString = Int(str) // Optional Int형
if intFromString != nil {
print("값은 \(intFromString) 입니다.")
} else {
print("변환 실패")
}
옵셔널 바인딩(Optional Binding)이란 if구문 내에서 조건식 대신 옵셔널 값을 일반 상수나 변수에 할당하는 구문을 사용하는 방식이다.
옵셔널 바인딩은 조건문 내에서 일반 상수에 옵셔널 값을 대입하는 방식
으로 이루어진다.
//if문을 이용한 Optional Binding
var str = "123"
if let intFromStr = Int(str) {
print("값은 \(intFromString) 입니다.")
} else {
print("변환 실패")
}
//guard문을 이용한 Optional Binding
var str = "123"
guard let intFromStr = Int(str) else {
print("변환 실패")
return
}
print("값은 \(intFromString) 입니다.")
guard문의 경우 진행이 불가능할 정도로 큼 일이 생길때만 사용
옵셔널 강제해제나 옵셔널 바인딩을 하지 않아도 컴파일러가 자동으로 해제해주는 경우가 있다.
비교연산의 경우 옵셔널을 해제하지 않아도 자동으로 연산을 수행
let tempInt = Int("1234")
tempInt == 123 // true
tempInt == Optional(123) // true
tempInt! == 123 // true
tempInt! == Optional(123) // true
값을 사용할 때 자동으로 옵셔널이 해제되기 때문에 굳이 ! 연산자를 사용하지 않아도 된다.
변수의 값이 nil이 될 가능성이 있다면 묵시적 옵셔널 해제를 사용하면 안된다.
let str: String? = "Optional"
var str2: String! = "Not Optional"
print(str) //Optional("Optional")
print(str2) //Not Optional
str2 = nil // 문제 없음
var val: Int? = 5
val + 5 // 오류 - Optional Int + Int
var val2: Int! = 5
val2 + 5 // 10
// 형식상 옵셔널로 정의하지만 실제로 사용할 때에는 절대 nil이 될 가능성이 없는 변수일 때 묵시적 해제 사용
var value: Int! = Int("123")
옵셔널을 해제하려면 if구문을 통해 정상값 여부를 검사해야한다.
하지만 다음 코드와 같은 경우 코드가 상당히 복잡해진다.
struct Company {
var ceo: Human?
var companyName: String?
}
struct Human {
var name: String?
var man: Bool = true
}
var startUp: Company? = Company(ceo: Human(name: "나대표", man: false), companyName: "루비페이퍼")
// 옵셔널 해제가 까다로움
if let company = startUp {
if let ceo = company.ceo {
if let name = ceo.name {
print("대표 이름 : \(name)")
}
}
}
// 간단하게 하기 위해 !강제해제를 사용할 경우 런타임 에러 확률이 높다
if let name = startup!.ceo!.name {
print(name)
}
이런 경우 옵셔널 체인
을 사용한다.
안정성 검사를 하지 않고 메소드나 프로퍼티를 호출하더라도 오류가 발생하지 않는 문법을 옵셔널 스타일을 이용하여 구현
startUp?.ceo
는 startUp이 nil이 아닐 때 동작하고 nil이면 아무 동작도 하지 않는다.
따라서 위의 코드는 다음과 같이 사용할 수 있다.
if let name = startUp?.ceo?.name { //마지막 name은 옵셔널 체인에 해당하지 않음
print("대표 이름 : \(name)")
}
옵셔널 체인에는 다음과 같은 특징이 있다.
//ex)
let name = startUp?.ceo?.name
print(name) // Optional("나대표")
//Optional(Optional(Optional(123))) == Optional(123)
따라서
옵셔널 체인 구문 : startup!.ceo!.name과
옵셔널 강제 해제 구문 : startup?.ceo?.name은
비슷하지만, 옵셔널 체인에서는 nil 오류가 발생하지 않는다
는 차이가 있다.