개발

SwiftUI) @State 변수란?, View 라이프사이클? - 사용하다 느낀 정의?

소소ing 2022. 5. 3. 16:35
반응형

SwiftUI는 기존 StroryBoard와 UI 구성 방식이 완전히 다르다고 볼 수 있다.

SwiftUI를 선언형 UI 프레임워크로 보통 이야기 한다. 

 

기존 StroryBoard의 각 화면마다 UIViewController가 할당되어 화면 생성 시 호출되는 라이프사이클로 화면 갱신 등의 처리를 해주었지만 SwiftUI의 경우는 View 단위 화면 구성으로 화면 갱신을 처리는 방식이 사뭇 다르다.

 

SwiftUI의 View를 생성하면 아래와 같이 생성된다. 

import SwiftUI

struct MainView: View {
    var body: some View {
        Text("MainView")
    }
}

struct MainView_Previews: PreviewProvider {
    static var previews: some View {
        MainView()
    }
}

 

구동되는 방식을 예측해보면 Previews에서 MianView()를 호출함에 따라 body가 실행되어 화면에 MainView가 출력되는것을 볼 수 있다. 

그럼 UIViewController 라이프사이클을 보면 viewWillAppear, viewDidAppear 함수를 통해 화면이 다시 보여질때마다 특정한 기능을 지정해 줄 수 있으며 viewWillDisappear, viewDidDisappear를 통해 화면이 사라질때마다 특정한 기능도 수행 할 수 있다. 

 

SwiftUI의 View에서는 onAppear와 onDisappear만을 이용할 수 있다. 이를 통해 화면이 보여질때와 사라질때 기능을 수행 할 수 있다. 

하지만 SwiftUI는 UIViewController와 다르게 @State 변수를 이용하여 @State 변수의 값이 변경되면 SwiftUI View의 body 부분에서 @State 변수를 가지고 있는 컨포넌트 부분이 새로 호출되도록 설계가 되어 있는 특징이 있다. 

SwiftUI의 화면 갱신은 값에 따른 변화를 이용한다고 생각하면 조금은 쉽게 이해가 될 듯 하다.

 

예를 들어보자

SplashView -> MainView로 이동한다고 가정할때 아래와 같은 상태 변경에 따른 화면 이동이 가능해진다. 

import SwiftUI

struct SplashView: View {
    @State private var isGoMain = false
    
    var body: some View {
        // @State 변수 값 변경으로 SplashView의 body 부분이 다시 호출되어 MainView를 호출한다.
        if isGoMain {
            MainView()
        } else {
            VStack {
                Spacer().frame(height: 189)
                Image("logo")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 198, height: 35)
                Spacer()
            }
            // 화면이 보여질때 호출되는 함수 - 최초 View 진입에서도 호출된다.
            .onAppear {
                // 몇 초 뒤 또는 기타 액션을 수행하는 로직을 넣고 조건이 충족될때 isGoMain 변수값을 변경하면 SplashView의 body 부분이 다시 호출되는 효과가 발생된다.
                isGoMain = true
            }
        }
    }
}

struct SplashView_Previews: PreviewProvider {
    static var previews: some View {
        SplashView()
    }
}

그렇다면 @State 변수 값 변경이 아닌 MainView()를 직접 호출을 하면 안되는 걸까?

간단하게 이야기 하자면 body 부분에서 화면이 그려지는 부분 즉 VStack 영역 안이 아니라면 바로 이동이 가능하지만 화면이 그려지는 영역 안에서 특정 조건 달성 시 MainView()를 호출하려고 하면 Result of 'MainView' initializer is unused Warring 메시지가 노출되며 이동이 되지 않는다. 

반응형