[Swift] 옵셔널

한음·2022년 3월 6일
0

옵셔널 타입

nil 을 사용할 수 있는 타입과 없는 타입을 구분하고, 사용할 수 있는 타입을 옵셔널 타입이라고 부른다.

스위프트는 안정성을 위해 되도록 오류를 반환하지 않도록 설계되었음.
다음과 같은 경우에도 오류로 처리하는 것이 아니라 nil 을 반환함.

let dic = ["a": "A", "b": "B"]
print(dic["c"]) // nil
print(Int("hello")) // nil

이때, 일반 자료형은 nil 값을 가질 수 없도록 제약을 가짐.
예를들어, 문자열 or 정수 타입은 일반 자료형이기 때문에 nil 값을 가질 수 없다.

var a = 123
a = nil // 'nil' cannot be assigned to type 'Int'

옵셔널 타입은 nil 값을 저장할 수 있다. nil 을 저장해야 하거나, 함수의 반환값에 nil이 포함될 가능성이 있다면 -> 오류가 발생할 가능성이 있다면, 반환 타입을 옵셔널 타입으로 지정해야 함.
위 예시로 알 수 있듯이 Int() 의 반환 타입은 옵셔널 타입임.

여기서 옵셔널 타입이란, 값을 옵셔널 객체 로 한 번 감싼 형태를 의미함. 함수 반환 타입을 옵셔널 타입으로 지정했을 경우, 오류가 발생하지 않고 정상 값을 반환하더라도 옵셔널 객체로 감싼 값이 반환됨.

print(Int("123")) // Optional(123)

이 객체는 옵셔널 언래핑 과정을 통해 실제 값을 추출해 사용.


옵셔널 타입 선언과 정의

? 를 붙여 일반 타입을 옵셔널 타입으로 만들 수 있다.

var optInt : Int?
var optStr : String?
var optArr : [Int]? // 옵셔널 Array
var optArr2 : [Int?] // 원소가 옵셔널 타입 Array
var optClass: AnyObject?

optArr2 = [1, 2, nil]
print(optArr2) // [Optional(1), Optional(2), nil]

옵셔널 값 처리

옵셔널 해제(옵셔널 언래핑) 과정을 거쳐야 본래 값의 타입으로 사용할 수 있다.
해제 방법은 아래와 같이 나뉜다.

- 명시적 해제
	- 강제 해제
    - 비강제 해제
    
- 묵시적 해제
	- 컴파일러에 의한 자동 해제
    - ! 연산자를 사용한 자동 해제
    

> 강제 해제

옵셔널 타입 값 뒤에 ! 를 붙여준다. - 강제 해제 연산자

var optInt: Int? = 3
print(optInt) // Optional(3)
print(optInt!) // 3

> 옵셔널 바인딩 ( 비강제 해제 )

조건문 내에서 일반 상수에 옵셔널 값을 대입하는 방식으로 이루어짐.

let str = "Swift"
if let strToInt = Int(str) {
    print(strToInt) // strToInt 는 일반 자료형으로 변환.
} else {
    print("변환 실패")
}

// 위와 같은 형태로 옵셔널이 조건식으로 들어갈 시, nil 이 반환되는 상황에는 false 처리됨.
// 하지만 조건식에 직접 nil 을 넣으면 오류.

func intStr(str: String) {
    guard let intFromStr = Int(str) else { // guard 문에서도 가능.
        print("값 변환 실패")
        return
    }
    print(intFromStr)
}

var opt : Int? = 22
if let unwrapOpt = opt, unwrapOpt >= 20 { // && 없이 추가 조건식
	print(unwrapOpt) 
}

> 컴파일러에 의한 자동 해제

옵셔널 타입 변수는 연산이나 해당 타입 메소드 사용이 불가함.
**비교 연산자 == != 를 사용하는 경우에만 옵셔널 해제를 않아도 됨.
한쪽이 옵셔널, 한쪽이 일반 타입으로 비교 연산 진행하면 자동으로 해제 후 비교 연산 수행.

var OptInt : Int? = 30
if OptInt != 20 {
	print(OptInt) // Optional(30)
}
// == != 연산에서만 사용 가능한듯. 다른 비교 연산자는 안된다.

묵시적 해제

swift3 부터 사라진 듯 하다.
! 를 이용하면 해제는 안되지만, 값이 있다는 가정 하에 돌아가기 때문에 메소드, 연산등을 사용 가능하다.

var a : String? = "hello"
print(a) // Optional("hello")
// print(a.count) 옵셔널이기 때문에 count 메소드 사용 불가

var b : String! = "Hello"
print(b) // 값은 Optional("Hello") 반환.
print(b.count) // 메소드 사용 가능

var c : Int! = 32
print(c + 32) // 64 -> 연산 가능
  • 추가

nil 병합 연산자

값이 nil 일 경우 기본 값을 만들어준다.

var a:Int? = 32
print(a ?? 100) // 32
profile
https://github.com/0hhanum

0개의 댓글