옵셔널은 에러 발생을 막기 위한 문법으로 번역하면 '선택적인'이라는 뜻이다. 어떤 값을 가질지 말지 선택적으로 가질 수 있다. 값이 없다면 해당 값을 nil로 나타내고, 옵셔널을 선언하기 위해선 타입을 선언할 때 ?를 붙이면 된다.
var name1: String?
var name2: String
print(name1)
print(name2)
name1은 에러를 발생시키지 않고 name2는 에러를 발생시킨다. name1의 출력결과는 nil이다.
변수에 값이 없고 그 값에 접근하려면 항상 에러가 발생하기 때문에 그걸 방지하기 위해 옵셔널을 사용한다. 값이 할당 되지 않는 경우가 조금이라도 있다면 결국 옵셔널을 쓰는게 안전하다.
var operand1: Int? = 3
var operand2: Int? = 5
print(operand1)
print(operand2)
print(operand1 + operand2)
위 코드도 에러가 발생하는 코드다. print(operand1)의 결과는 3이 아니라 Optional(3) 이고 옵셔널로 Wrapping 되어있는 경우 연산이 불가능하다. 따라서 각 변수에 있는 옵셔널을 벗겨내줘야 한다.
print(operand1! + operand2!)
!를 이용해서 강제로 언래핑 시킨다. 언래핑 시킨 변수가 nil값을 가지고 있다면 에러가 발생하니 조심해서 이용해야 된다.
바인딩은 if, guard를 사용하는 두가지 방법이 있다. 개인적으로는 guard가 가독성이 좋고 코드 줄도 짧아져서 더 선호한다.
func printfResult(operand1: Int?, operand2: Int?) {
guard let operand1 = operand1 else { return }
guard let operand2 = operand2 else { return }
print(operand1 + operand2)
}
var operand1: Int? = 3
var operand2: Int? = 5
print(operand1)
print(operand2)
printfResult(operand1: operand1, operand2: operand2)
guard 구문은 반드시 return이 사용되기 때문에 함수를 만들어서 사용해야 한다. 메인 함수에서 사용한다면 갑자기 종료될 수 있다.
var operand1: Int? = 3
var operand2: Int? = 5
print(operand1)
print(operand2)
if let unwrapped1 = operand1 {
if let unwrapped2 = operand2 {
print(unwrapped1 + unwrapped2)
}
}
옵셔널 선언을 위해 ? 를 쓰지않고 !를 쓴다. 똑같이 옵셔널인데, Non-Optional-Type에 값을 할당할 때 자동으로 값을 추출해준다.
var operand1: Int! = 3
var operand2: Int! = 5
var unwrapped1: Int = operand1
var unwrapped2: Int = operand2
print(unwrapped1 + unwrapped2)
Int? 타입이었으면 unwrapped1에 값이 정상적으로 할당되지 않는다. 위에서 말한 것처럼 unwrapped1이 Non-Optional-Type이고 여기서 값을 할당하고 있으니 자동으로 3이라는 값이 언래핑되어 추출된 것이다. IUO가 아니라 일반적인 옵셔널을 썻다면 값이 할당되지 않고 에러가 발생한다.