Search

Optional (옵셔널)

생성일
2023/06/30 03:53
태그
Grammar

Optional❗️

옵셔널은 단어 뜻 그대로 ‘선택적인’, 즉 값이 ‘있을 수도, 없을 수도 있음’을 나타내는 표현이다.
이는 ‘변수나 상수 등에 꼭 값이 있다는 것을 보장할 수 없다. 즉, 변수 또는 상수의 값이 nil 일 수도 있다’ 는 것을 의미한다.
옵셔널의 사용은 많은 의미를 축약하여 표현하는 것과 같다. 옵셔널을 읽을 때 ‘해당 변수 또는 상수에는 값이 없을 수 있다. 즉, 변수 또는 상수가 nil일 수도 있으므로 사용에 주의하라’는 뜻으로 받아들일 수 있다.
nil 은 옵셔널로 선언된 곳에서만 사용될 수 있다.
옵셔널은 어떤 상황에 사용할까? 왜 굳이 nil 이 있음을 가정해야 할까?
이 질문에 답할 수 있는 예로, 우리가 만든 함수에 전달되는 전달인자의 값이 잘못된 값일 경우, 제대로 처리하지 못했음을 nil 로 반환하여 표현하는 것을 들 수 있다.
간단히 nil 을 반환해서 오류가 있음을 알릴 수 있다.
또는 매개변수를 굳이 넘기지 않아도 된다는 뜻으로 매개변수의 타입을 옵셔널로 정의할 수도 있다.
스위프트 프로그래밍을 하면서 매개변수가 옵셔널일 때는 ‘아, 이 매개변수에는 값이 없어도 되는구나’ 라는 것을 API 문서를 보지 않고도 알아야 한다.
옵셔널은 열거형으로 구현되어 있다.
public enum Optional<Wrapped> : ExpressibleByNilLiteral { case none case some(Wrapped) public init(_ some: Wrapped) // ... }
Swift
복사
옵셔널은 제네릭이 적용된 열거형이다.
nil 일 때는 none 케이스, 값이 있는 경우 는 some 케이스가 되는데, 연관값으로 Wrapped 가 있다. 따라서 옵셔널에 값이 있으면 some의 연관 값인 Wrapped에 값이 할당된다.
즉, 옵셔널이라는 열거형의 방패막에 보호되어 래핑되어 있는 모습이라는 것이다.

옵셔널 추출

1. Force Unwrapping (강제 추출)

optional!
Swift
복사
옵셔널의 값을 추출하는 가장 간단하지만 가장 위험한 방법 이다.
런타임 오류가 일어날 가능성이 가장 높기 때문이다. 또 옵셔널을 만든 의미가 무색해지는 방법이기도 하다.
옵셔널의 값을 강제 추출하려면 옵셔널 값의 뒤에 느낌표(!) 를 붙여주면 값을 강제로 추출하여 반환해준다.
만약 강제 추출 시 옵셔널에 값이 없다면, 즉 nil 이라면 런타임 오류가 발생한다.

2. Check for nil value

if optional != nil { optional! }
Swift
복사

3. Optional Binding (옵셔널 바인딩)

if let safeOptional = optional { safeOptional } // 옵셔널 변수가 값이 있다면, 언래핑해서 일반 상수 safeOptional // 에 대입하고 if문 실행 // 값이 없다면, if문의 조건이 거짓이 되어 if문을 실행하지 않는다.
Swift
복사
위의 방식을 사용하면 옵셔널을 사용하는 의미가 사라진다. 그래서 스위프트는 조금 더 안전하고 세련된 방법으로 옵셔널을 unwrapping하는 옵셔널 바인딩 을 제공한다.
if let name: Type = OptionalExpression { } while let name: Type = OptionalExpression { } // 거의 안씀 guard let name: Type = OptionalExpression else { }
Swift
복사
옵셔널 바인딩은 옵셔널에 값이 있는지 확인할 때 사용한다. 만약 옵셔널에 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 옵셔널이 아닌 형태로 사용할 수 있도록 해준다.
옵셔널 바인딩은 if 또는 while 구문 등과 결합하여 사용할 수 있다.
var myName: String? = "HJ" // 옵셔널 바인딩을 통한 임시 상수 할당 if let name = myName { print("My name is \(name)") else { print("myName == nil") } // My name is HJ // 옵셔널 바인딩을 통한 임시 변수 할당 if var name = myName { name = "emptyhead" print("My name is \(name)") } else { print("myName == nil") } // My name is emptyhead guard let name = myName else { return } print(name) // HJ
Swift
복사
guard문이 if 문과 다른 점은 옵셔널 바인딩 된 상수 name의 scope가 다르다는 점이다.

IUO (묵시적 추출)

별도의 추출하는 과정을 거치지 않아도 자동으로 옵셔널이 해제되는 것
let name: String!
Swift
복사
IUO도 옵셔널 타입으로 선언하는 방법 중 하나이다.
하지만 Non-Optional Type으로 처리되어야 할 때 값을 자동으로 추출해준다. → 특정 조건일 때만!
var num: Int! = 4 var num2: Int = num // IUO Ex print(num2) // 4
Swift
복사
IUO를 쓴다고 원하는 때에 자동으로 값이 언래핑 되는 것이 아니다.
옵셔널 타입을 Non-Optional Type에 대입할 때 별도의 추출과정 없이 대입이 가능한 것이다.
하지만 강제추출쓰..
언제 사용?
스토리보드 사용시 @IBOutlet 할 때 ㅋㅋ

4. ?? Nil Coalescing Operator

optional ?? defaultValue
Swift
복사
Ex)
if let name = name { print("hello, \(name)") } else { print("hello, what's your name?") }
Swift
복사
이거를
print("hello, " + (name ?? "what's your name?"))
Swift
복사
이렇게 간단하게 만들 수 있다.
주의할 점은 Nil-Coalescing에 사용되는 Optional Type과 Non-Optional Type은 Optional을 제외하면 동일한 Type이어야 한다.
Optional String Type ?? Non-Optional String Type(O) Optional String Type ?? Non-Optional Int Type(X)
Swift
복사

5. Optional Chaining

optional?.property optional?.method()
Swift
복사

 Reference