SWIFTUI/Grammar

SwiftUI : If let과 Guard

서근 2021. 5. 14. 22:16
반응형

If let / Guard

안전한 코딩은 정말 좋은 코드입니다. 값이 있는지 없는지 선택적 변수인지의 여부 등을 안전하게 나타내 줍니다.

 

안전한 코딩에는 if letguard let이 있습니다.

 

If let의 대안은 guard let이며 unwrapping 옵셔널도 이에 해당합니다. guard let은 우리를 위해 언래핑 되지만, 내부에서 nil을 찾으면 사용한 함수, 루프 또는 조건을 종료할 수 있습니다.

 

guard let 도 if let과 비슷하지만 다른 점이 있습니다.

 

guard라는 것은 지키다 라는 뜻처럼, guard 문은 특성상 함수(메서드)에서만 쓰이며, guard구문의 조건을 만족하지 못하면 else문으로 빠져서 함수의 실행을 종료시킬 때 사용합니다.

If let

SwiftUI에서 사용해보도록 하겠습니다.

import SwiftUI

struct ContentView: View {
    
    @State var title: String = ""
    @State var isLoading: Bool = false
    
    // MARK: BODY
    var body: some View {
        NavigationView {
            VStack {
                Text("안녕하세요 서근 개발 블로그입니다.")
                
                Text(title)
                
                if isLoading {
                    ProgressView()
                }
                
                Text(isLoading.description)
                    .foregroundColor(isLoading ? Color.blue : Color.red)
                
            }
            .navigationBarTitle("Safe Coding")
            
            .onAppear {
                data()
            }
        }
    }
    func data() {
        isLoading = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        title = "빡코딩 합시다!"
            isLoading = false
        }
    }
}

// MARK: PRESVIVEWS
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

이 코드는 프리뷰가 실행되면 ProgressView가 실행되고 3초 후에 "빡코딩 합시다!"라는 문구가 나오게 됩니다. 함수에 isLoadingtrue로 넣어 줬고 title이 나오면 다시 isLoadingfalse로 설정해줬습니다.

 

만약 처음부터 titlenil이라면 어떨까요? @State var titlenil로 설정해보겠습니다.

struct ContentView: View {
    
    @State var title: String? = nil
    @State var isLoading: Bool = false

Text(title)이 오류가 났죠?

Value of optional type 'String?' must be unwrapped to a value of type 'String'

옵셔널 타입이 왔기 때문에 String인지 Int타입인지 Xcode는 알지 못합니다. 이럴 때 if let문을 사용할 수 있습니다.

    // MARK: BODY
    var body: some View {
        NavigationView {
            VStack {
                Text("안녕하세요 서근 개발 블로그입니다.")
                
                if let text = title {
                Text(text)
                }

만약 title에 값이 있으면 titlenil이 아니다. 그렇기 때문에 title이라는 새 변수를 만들어라.라는 뜻입니다.

 

즉, 실제 값이 있으면 true가 되므로 코드를 실행하는 것이죠. 하지만 title에 값이 없으면 생성할 수 없습니다. 이개체는 절대 실행되지 않으며 개체를 건너뛰게 됩니다.

 

한 가지 예를 들어볼 텐데 만약 로그인되어있는 사용자가 있고, 그렇지 않은 사용자가 있다고 가정했을 때 화면에 로그인되어있는 유저의 아이디를 나타내 주고 만약 로그인되어있지 않은 사용자가 있다면 대체 문구를 나오게 해 줄 수 있습니다.

    func data() {
        
        if let userID = currentID {
            isLoading = true
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                title = "로그인 되어있는 아이디 : \(userID)"
                isLoading = false
            }
        } else {
            title = "계속하려면 로그인해주세요."
        }
    }

프리뷰를 실행해보면 당연시 currentIDnil이기 때문에 화면에 "계속하려면 로그인해주세요."라는 문구가 뜹니다. 그럼 만약 nil이 아닌 값을 부여해준다면 어떨까요?

이렇게 값이 있다면 if let 함수를 실행할 것이고 만약 값이 없다면 else문을 실행하게 됩니다. 

 

다른 방법으로는 guard let을 사용할 수 있습니다. if letguard let은 동일하게 작동하지만 사용방법만 약간 다를 뿐입니다.

Guard let

data2라는 함수를 생성하고 아래와 같이 코드를 작성하겠습니다. guard let은 항상 뒤에 else가 와야 하고 return이 반드시 같이 와야 합니다.

    func data2() {
        guard let userID = currentID else {
            
            return
        }
    }

그리고 실행될 함수는 아래와 같습니다.

    func data2() {
        guard let userID = currentID else {
            title = "계속하려면 로그인해주세요."
            return
        }
    }

이제 만약 값이 있다면 실행될 코드를 넣어줘야 합니다.

    func data2() {
        guard let userID = currentID else {
            title = "계속하려면 로그인해주세요."
            return
        }
        isLoading = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            title = "로그인 되어있는 아이디 : \(userID)"
            isLoading = false
        }
    }

bodyonAppear data()data2()로 수정하고 런해보겠습니다.

 

동일하게 실행되죠? 이처럼 if let과 guard let은 동일하게 사용됩니다.

 

읽어주셔서 감사합니다.🤟