SwiftUI의 생명주기는 크게 앱의 생명주기와 뷰의 생명주기로 나눌 수 있습니다.
@main
은 App 프로토콜을 따르는 구조체로, C나 java에서 main 함수와 같이 앱의 진입점이 됩니다.
만약 App 프로토콜을 명시하지 않는다면 컴파일 에러가 발생하기 때문에 꼭 함께 작성해 줘야 합니다.
또한 init() 메서드를 통해 앱의 초기 설정을 수행할 수 있습니다.
@main
struct MyApp: App {
init() {
// 앱 초기 설정
print("App is initializing")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
init() 메서드를 사용하는 이유는 앱 실행 전 초기화 해야 할 작업들을 수행하기 위해서 입니다.
예를 들어 앱이 시작될 때 네트워크를 연결하거나 초기 데이터를 받아오는 등의 작업을 처리할 수 있습니다.
@main
struct MyApp: App {
init() {
// 앱 초기 설정
print("App is initializing")
setupLogging()
preloadData()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
func setupLogging() {
// 로깅 설정 코드
}
func preloadData() {
// 초기 데이터 로드 코드
}
}
이처럼 init() 메서드는 특정 작업을 앱 시작 전에 미리 해야 할 경우에 사용하기 때문에 없어도 앱을 실행하는데 문제가 되지 않습니다.
body 속성에서 뷰 계층 구조의 루트를 설정합니다.
앱의 상태가 변경될 때 실행할 코드를 정의할 수 있습니다.
import SwiftUI
@main
struct MyApp: App {
@Environment(\.scenePhase) var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { newPhase in
switch newPhase {
case .active:
print("App is active")
case .inactive:
print("App is inactive")
case .background:
print("App is in background")
@unknown default:
print("Unexpected state")
}
}
}
}
뷰의 생명주기는 SwiftUI의 View 프로토콜을 따르는 구조체에서 관리됩니다.
주요 단계는 아래와 같습니다.
뷰가 생성될 때 초기 설정 수행합니다.
뷰의 내용을 정의하여 화면에 그릴 수 있도록 합니다.
struct ContentView: View {
var body: some View {
Text("Hello, World!")
}
}
뷰의 상태가 변경될 때마다 뷰가 다시 렌더링 됩니다.
struct ContentView: View {
@State private var counter = 0
var body: some View {
VStack {
Text("Counter: \(counter)")
Button(action: {
counter += 1
}) {
Text("Increment")
}
}
}
}
뷰가 화면에 나타날 때와 사라질 때 실행할 코드를 정의할 수 있습니다.
struct ContentView: View {
var body: some View {
Text("Hello, World!")
.onAppear {
print("ContentView appeared!")
}
.onDisappear {
print("ContentView disappeared!")
}
}
}
onAppear와 onDisappear의 정의는 다음과 같습니다.
nonisolated
func onAppear(perform action: (() -> Void)? = nil) -> some View
공식문서에서 설명은 view가 나타날 때 수행할 action을 추가한다고 되어 있습니다.
perfome은 옵셔널이기 때문에 아무것도 작성하지 않는 것도 가능합니다.
nonisolated
func onDisappear(perform action: (() -> Void)? = nil) -> some View
onDisappear도 onAppear과 정의는 같습니다..
따라서 onAppear은 화면이 나타날때 호출되는 함수이고, onDisappear은 화면이 사라질 때 호출되는 함수라는 것 외에 사용법은 동일합니다.
뷰가 메모리에서 제거될 때 정리 작업을 수행합니다.
아래는 SwiftUI의 뷰 생명주기를 보여주는 전체 코드입니다.
import SwiftUI
@main
struct MyApp: App {
@Environment(\.scenePhase) var scenePhase
init() {
print("App is initializing")
}
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { newPhase in
switch newPhase {
case .active:
print("App is active")
case .inactive:
print("App is inactive")
case .background:
print("App is in background")
@unknown default:
print("Unexpected state")
}
}
}
}
struct ContentView: View {
@State private var isPresented = false
var body: some View {
VStack {
Text("Hello, World!")
.onAppear {
print("ContentView appeared!")
}
.onDisappear {
print("ContentView disappeared!")
}
Button(action: {
isPresented.toggle()
}) {
Text("Toggle View")
}
if isPresented {
SecondView()
}
}
}
}
struct SecondView: View {
var body: some View {
Text("This is the second view")
.onAppear {
print("SecondView appeared!")
}
.onDisappear {
print("SecondView disappeared!")
}
}
}
@main
: 앱의 진입점으로, App
프로토콜을 준수해야 합니다.init()
메서드를 사용하여 앱의 초기 설정을 수행합니다.body
속성에서 뷰의 내용을 정의하여 화면에 그립니다.@State
, @Binding
, @Environment
등을 사용하여 뷰의 상태가 변경될 때마다 뷰를 다시 렌더링합니다.onAppear
와 onDisappear
를 사용하여 뷰가 화면에 나타날 때와 사라질 때 실행할 코드를 정의합니다.오늘은 SwiftUI의 생명주기에 대해 알아봤습니다.
대략적으로 알고는 있었지만, 이렇게 글로 정리해 보는건 처음이네요.
생명주기를 알면 앱의 전체 흐름을 이해할 수 있기 때문에 중요한 부분인거 같습니다. 흐름을 이해한다는 것은 예상치 못한 오류가 발생하여도 오류를 제거하기가 수월해지고, 뿐만 아니라 앱을 효율적으로 만들 수도 있기 때문입니다.
이 글을 읽는 분들도 개념 정리가 잘 되었으면 좋겠습니다.
출처
https://velog.io/@luke_kong/SwiftUI-생명주기-이벤트-핸들링의-모든-것
https://zeddios.tistory.com/936
https://developer.apple.com/documentation/swiftui/view/ondisappear(perform:)
https://developer.apple.com/documentation/swiftui/view/onappear(perform:)