Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Basic)

47. [SwiftUI] Optional Unwrapping( if let / guard let )

by Toughie 2023. 5. 2.

옵셔널 값을 안전하게 벗겨내는 (Unwrapping) 하는 방법에 대해 알아보자.

주로 if let 바인딩, guard let 바인딩을 사용한다.

 

왜 옵셔널 값을 안전하게 벗겨내야 하는가?

간혹 옵셔널 값에 ! 느낌표를 붙여서 강제로 언래핑 하는 코드를 본적이 있었을 것이다.

-> 앱이 꺼질 수 있다...!

 

먼저 옵셔널 변수는 값이 없을 수도 있기 때문에, 변수를 사용하기 전에 nil체크를 꼭 해줘야 한다.

(예: var a: Int?로 변수를 선언하면 자동으로 nil이 할당된다. var a: Int? = nil과 같음)

만약 옵셔널 변수에 값이 할당이 되어 있지 않는데 !을 사용해 강제로 언래핑을 시도하면

런타임 오류가 발생한다.(앱이 꺼지는, 크래시가 난다.)

 

WHY?

옵셔널 변수를 선언하면 nil이 자동으로 할당되면서 해당 변수가 메모리 공간을 차지하지만,

(강제 언래핑을 하면) 그 안에는 실제 값이 없기 때문에 메모리에 값을 찾지 못하기 때문에 크래시가 발생하는 것이다.

 

그래서 바인딩이란?

먼저 바인딩은 Optional 값을 새로운 상수나 변수에 할당하는 작업을 말한다.

아주 아름다운 방식이다. 만약 optional 값이 nil인 경우는 새로운 상수나 변수에 할당이 안되기 때문!

 

guard let 바인딩

Optional 값이 nil이 아닌 경우, 해당 값을 새로운 상수나 변수에 할당하고

guard let 구문 아래의 코드에서 그 값을 안전하게 사용할 수 있게 한다.

만약 guard let 구문 안에서 Optional 값이 nil이라 바인딩이 안되면, else 블록이 실행되면서 

guard let 구문 밖에서 해당 값을 사용하는 코드가 실행되지 않는다. 

 

Early Exit! 조기 종료의 개념이다.

+ guard let 바인딩은 함수 내부에서만 사용할 수 있다.

if let 바인딩

guard let 바인딩과 유사하게 Optional 값이 nil이 아닌 경우 해당 값을 새로운 상수나 변수에 할당하고

if 구문(클로저) 내부의 코드가 실행된다. 

Optional 값이 nil이라 바인딩에 실패하면 if 구문 내부의 코드가 아예 실행되지 않는다.

 

같은 맥락이지만, guard let 바인딩을 가독성 측면에서 선호하는 편이다.

 

-> 결국 Optional 값을 안전하게 추출하기 위한 방법들이고, Optional 값이 nil인 경우에 처리할 수 있도록 하는 것이다.

 

 

-> 유저의 ID에 대한 nil 체크를 하고, 성공하면 displayText에 값을 할당한 후 아이디를 출력하는 예시이다.

 바인딩에 실패하는 경우 에러 메세지를 띄운다.(여기서는 displayText에 에러 메세지를 할당하는 방식)

//  Created by Toughie on 2023/05/02.
//

import SwiftUI

struct OptinalUnwrapping: View {
    
    @State var currentUserID: String? = "7"
    @State var displayText: String?
    @State var isLoading: Bool = false
    
    var body: some View {
        NavigationView {
            VStack {
                Text("SAFE CODING")
                if let text = displayText {
                    Text(text)
                        .font(.title)
                }
                //절 대 강 제 언 래 핑 하 지 마
//                Text(displayText!)
//                    .font(.title)
                if isLoading {
                    ProgressView()
                }
                Spacer()
            }
            .navigationTitle("SAFE CODING")
            .onAppear {
                loadData2()
            }
        }
    }
    
    private func loadData() {
        if let userID = currentUserID {
            isLoading = true
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                displayText = "Welcome! userID: \(userID)"
                isLoading = false
            }
        } else {
            displayText = "Error: There is no User ID!"
        }
    }
    
    private func loadData2() {
        guard let userID = currentUserID else {
            displayText = "Error: There is no User ID!"
            return
        }
        isLoading = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            displayText = "Welcome! userID: \(userID)"
            isLoading = false
        }
    }
}

 

요약
옵셔널 값이 있으면 강제 언래핑 절대 하지 말고,

if let / guard let 바인딩으로 안전하게 옵셔널 값을 처리하자 :)