공부/SWIFT

[SWIFT] 옵셔널( Optional ) ★★★★★

알로하리미 2021. 3. 11. 10:46
728x90

1. 개요

키워드 물음표 ? (접미사)

말 그대로 선택적인 : 값이 "있을 수도 있고 없을 수도 있다"라는 의미

값이 있다는 것을 보장 할 수 없다. 즉, nil일 수도 있다.

옵셔널과 옵셔널이 아닌 값은 철저히 다른 타입으로 인식된다.

즉 옵셔널의 사용은 nil이 전달되어도 되는 문서인지 아닌지를 눈으로 한 번에 파악이 가능하다.

옵셔널 변수 또는 상수가 아닐시에는 nil을 할당할 수 없다.( 0, "" 영이나 빈 값도 값이다. )

옵셔널은 열거형이다 (값이 있는 경우는 .some 없는경우(nil) .none으로 switch문에서 사용할 수 있다.)

 

 

2. 선언 및 할당

let shortForm: Int? = Int("42")
let longForm: Optional<Int> = Int("42")
print(longForm)
// prints "Optional(42)" 옵셔널로 감싸져있다.


longForm = nil
print(longForm == nil)
// Prints "true"


//옵셔널은 열거형이다. 위에 코드를 아래처럼 쓸수 있다.
let number: Int? = Optional.some(42)
let noNumber: Int? = Optional.none //nil을 넣은것과 같다.
print(noNumber == nil)
// Prints "true"

 

3. 옵셔널 추출 

옵셔널 강제 추출(Forced Unwrapping) 

키워드 느낌표 ! (접미사)

nil값은 없다라는 것을 확신했을 때만 사용 

위험한 방법  런타임 오류가 일어날 가능성이 높다.

값이 없다(nil)면 런타임 오류 발생

var myName: String? = "알로하리미"


//강제 추출하여 할당 
//추출하지 않으면 일반변수에는 옵셔널 값이 할당 될 수 없다.
var aloha: String = myName!


myName = nil
aloha = myName! //런타임 오류


// 무조건 선택적 연결을 수행 할 수도 있다.
let isPNG = imagePaths["star"]!.hasSuffix(".png")
print(isPNG)
// Prints "true"

 

 

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

옵셔널에 값이 있는지 없는지를 확인할 때 사용

if나 while 구문 등과 결합하여 사용 가능

예제 ) imagePaths Dictionary는 각 key 마다 String? 값을 갖고 있다고 가정했을 때

let imagePaths = ["star": "/glyphs/star.png",
                  "portrait": "/images/content/portrait.jpg",
                  "spacer": "/images/shared/spacer.gif"]

if let starPath = imagePaths["star"] {

    //블럭 안쪽에서만 임시 상수 starPath를 사용 할 수 있다.
    
    print("The star image is at '\(starPath)'")
    
} else {

    print("Couldn't find the star image")
    
}
// Prints "The star image is at '/glyphs/star.png'"

 

 

5. 옵셔널 체이닝 (따로 더 중점적으로 다룰 예정)

옵셔널 바인딩 보다 좀 더 편하게 옵셔널을 사용할 수 있다. 

체인처럼 연결하여 쓸 수 있다. 접미사 ?

if imagePaths["star"]?.hasSuffix(".png") == true {
    print("The star image is in PNG format")
}
// Prints "The star image is in PNG format"

 

 

6. nil 병합 연산자 사용(nil-coalescing)

키워드 ??     :    A ?? B  ( a가 nil이면 B를 반환 아니면 A를 반환 )

let defaultImagePath = "/images/default.png"
let heartPath = imagePaths["heart"] ?? defaultImagePath
print(heartPath)
// Prints "/images/default.png"



// 연결해서 사용 가능
let shapePath = imagePaths["cir"] ?? imagePaths["squ"] ?? defaultImagePath
print(shapePath)
// Prints "/images/default.png"

 

 

 

7. 암시적 추출 옵셔널 ( 이건 변수 선언 시 데이터 타입 뒤에 사용하는! 느낌표 )

로직상 nil 때문에 런타임 오류가 발생하지 않을 것 같다는 확신이 들 때!

nil을 할당해줄 수 있는 변수가 상수

암시적 추출 옵셔널 타입으로 지정된 변수나 상수는 일반 값처럼 사용 가능 nil도 할당 가능

하지만 옵셔널과 마찬가지로 nil이 할당되었을 때 접근하면 런타임 오류 발생

//암시적 추출 옵셔널 타입 선언 String!
var myName: String! = "알로하리미"
print(myName) 
//prints "알로하리미"

myName = nil
if let name = myName {
    print("My name is \(name)")
}
else{
    print("My name is nil")
}
// My name is nil

myName.isEmpty //nil에 접근시 런타인 오류 발생

 

 

* 암시적 , 강제 추출보단 옵셔널 바인딩, nil병합 연산자, 옵셔널 체이닝을 통해 사용하는 것이 안전하다.