Swift Optional(옵셔널)
- Optional은 Swift 언어에서 프로그램의 안정성을 높이기 위해 도입한 개념.
- 기존 프로그래밍 언어를 가지고 작업을 할때 가장 빈번히 발생하는 예외 중의 하나가 NULLPointerException임.
- NULLPointerException은 주로 변수(상수)메모리의 값을 할당 하지 않은 상태에서 해당 변수나 상수에 접근시 발생.
- Swift에서는 이러한 Nullpointerexception을 방지하기 위해서 Optional형식을 도입.
- Optioanl 형식은 nil을 저장할 수 있도록 자료형 * nil: 값이 없다는 뜻.
- optional 자료형을 만들고자 하는 경우에는 변수를 선언할 때 자료형 뒤에 ?나!를 붙여서 만듬.
- optional 자료형으로 만들어지면 nil을 저장할 수 있음.
- Optional 은 형식의 데이터를 wrapping을 해서 가지고 있음.
- 그래서, optional 자료형의 값은 일반 연산작업이 안되고 다른 자료형과 연산도 안됨. 프린트 함수를 사용하여 로그 출력을 해보면 되면 optional이 붙어서 출력됨.
중요:
-스위프트는 일반 자료형으로 변수를 선언하면 nil을 저장할 수 없음. (무조건 값을 할당하여 초기화를 해야 함.)
- 즉, 변수나 상수는 접근하기 전 반드시 “초기화"를 해줘야 함.
이해를 돕기 위해 아래 코드를 참고해 보자.
var su1 : Int // error
// swift에서는 위와 같이 변수선언을 할 수 없음. 스위프트에서는 optional타입이 아니면 nil을 저장할 수 없기때문.
// 아래처럼 ? 나 ! 를 형식뒤에 붙여 Optional 형식으로 사용해야 nil값을 저장할 수 있음.
var su2 : Int? = nil // OK
su2 = 30 // OK
var su1 : Int = 10 // OK
// 아래와 같이 optional타입은 연산에 사용할 수 없음.
var result : Int = su1 + su2 // su2가 옵셔널INT 형식이라 연산에 사용할 수 없어서 에러.
// optional type은 출력을 하게되면 optional이 붙어서 출력.
print("su1:", su1)
print("su2:", su2)
정리: optional 자료형의 값은 일반 연산작업이 안되고 다른 자료형과 연산도 안됨. 그래서 로그출력을 하게 되면 optional이 붙어서 출력됨.
중요 사항:
-
옵셔널 값을 사용하려면 반드시 unwrapping을 해야만 함.
-
아래 정리한 Optional Unwrapping 방법 중, 주의할 사항은 nil이 들어있는 변수(상수)를 강제 unwrapping하게 되면 critical error가 발생한다.
-
그래서, optional binding을 통해 값을 추출하는 것을 권장함.
옵셔널 Unwrapping
var num: Int? = nil
num = 123
print(num) → Optional(123)으로 출력됨.
-이해를 돕기위해 값이 상자 안에 포장되어 있다고 생각하면 좋음. 이 상자를 여는 것을 unwrapping이라고 함.
Optional해제 (unwrapping)
-
강제로 해제(Forced Unwrapping) : (비권장)
=> optional타입의 자료형을 선언할때 뒤에 !를 붙이면 강제로 해제
=> 데이터가 nil을 가지고 있으면 예외가 발생함.
=> 이 방법을 사용할 때는 if나 guard구문을 이용해서 nil이 아닐때만 수행하도록 하는 것이 좋음.
//optional을 강제로 해제해서 사용
print("su2", su2!)
var result : Int = su1 + su2!
print("result", result)
//강제 해제를 사용할 때 데이터가 nil이면 에러 발생
su2 = nil
print("su2:", su2!) //Fatal error: Unexpectedly found nil while unwrapping an Optional value
result = su1 + su2!
아래와 같은 방법으로 unwrapping.
if su2 != nil {
print("su2:", su2!)
result = su1 + su2!
} else {
print("su2가 nil이라서 작업을 계속할 수 없습니다.")
}
2. 컴파일러에 의한 자동해제
⇒ == 와 != 연산에 사용할 때는 컴파일러가 자동으로 해제해서 사용.
3. 묵시적 해제
=> 변수를 만들때 ? 대신에 !를 붙이면 변수 사용을 할 때 Optional을 해제하지 않아도 자동으로 해체가 됨.
=> nil 인 경우는 예외가 발생할 수 있음.
=> iOS에서는 Interface Builder에서 디자인 한 UI객체를 swift코드에 변수로 만들 때 이방법을 사용함.
var su3 : Int? = 34
// == 와 != 연산은 optional을 해제하지 않아도 가능.
print(su3 == 34)
// ? 대신에 !를 이용해서 변수를 만들면 optional을 해제하지 않아도 자동으로 해제해서 사용할 수 있도록 해줌.
var su4 : Int! = 76
print(su4 + 70)
4. 옵셔널 바인딩 (권장)
if let name:Type = optionalexpression {
statements
}
여기서 타입은 형식추론이 가능하기 때문에 생략가능.
if var도 가능.
OptionalExpression에서 값이 있는지 확인 후, 값이 있다면 name상수에 언랩핑 되어서 추출함.
Optional 표현식을 평가한 값을 언랩핑하여 상수에 저장함.
var num: Int? = nil
print(num!)
// 아래처럼 작성하는 경우는 거의 없음.
if num != nil {
print(num!)
}
정석 문법:
if let name:Type = optional expression {
statements
}
while let name: Type = optional expression {
statements
}
—————————————————————-
if let 바인딩할상수이름 = optional표현식 {
statements // 여기서만 바인딩된 상수를 쓸 수 있음.
}
if let 상수 이름 = 반드시옵셔널표현식이 와야 함. {
statements
}
중요: 바인딩된 상수는 if블럭 안에서만 사용할 수 있음.
중복 중첩되는 경우에는 guard let 사용. 주의: 가드문의 else block은 가드문자체가 아니라 가드문을 호출한 호출문을 종료시키는 것임.
guard let name:Type = optional expression else {
}
statements
'Swift' 카테고리의 다른 글
Swift - Self & Super (0) | 2020.03.22 |
---|---|
Swift - 고차 함수 (0) | 2020.03.21 |
Swift - First Class Citizen (0) | 2020.03.19 |
Swift - Closure(클로저) (0) | 2020.03.19 |
Swift - Function(함수) (2) | 2020.03.19 |