SWIFTUI/Grammar

SwiftUI : onAppear()

서근 2021. 5. 14. 00:02
반응형

onAppear()  

View 가 나타날 때  실행될 acttion을 추가합니다.

SwiftUIUIKitViewDidDisplay() 와 동등한 기능을 제공합니다. 원하는 모든 코드를 이 두 이벤트에 첨부할 수 있고, SwiftUI는 이벤트가 발생할 때 이것을 실행합니다.

 

즉 특정 뷰가 화면에 나타날 때 특정 항목을 로드합니다.

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView()) {
                    Text("onAppear() & onDisappear()")
                }
            }
        }
    }
}

struct DetailView: View {
    var body: some View {
        VStack {
            Text("Second View")
        }
        .onAppear {
                print("DetailView가 실행되었습니다.")
        }
        .onDisappear {
                print("DetailView가 종료되었습니다.")
        }
    }
}

위 코드처럼 작성 후에 디버그 창을 열어놓고 런을 해보면 아래와 같은 결과 값을 확인할 수 있습니다.

간단하게 코드로 예제를 들어보겠습니다.

 

우선 아래와 같이 Text를 지정해주고 onAppear로 화면이 로드되면 텍스트가 변경되도록 해주겠습니다.

import SwiftUI

struct OnAppearBootcamp: View {
    @State var title: String = "안녕하세요"
    var body: some View {
        NavigationView {
            ScrollView {
                Text(title)
            }
            .onAppear(perform: {
                title = "서근개발블로그"
            })
            .navigationBarTitle("onAppear Bootcamp")
        }
    }
}

title"안녕하세요" 라고 지정해줬지만 결과 화면을 보면 "서근 개발 블로그"라고 바로 로그가 되죠? 왜냐하면 onAppear은 특정 뷰가 화면에 나타날 때 지정했던 항목을 바로 보여주기 때문입니다.

 

이것을 확인해보려면 지연 효과를 주면 되는데 지연 효과를 주는 방법은 DispatchQueue를 사용하는것입니다.

 

처음에는 사용하기 어렵겠지만 사용하다보면 쉬운 코드이기 때문에 외우시는 걸 추천드립니다.

 DispatchQueue.main.asyncAfter(deadline: .now() + Double) {
    //some code
 }
struct OnAppearBootcamp: View {
    @State var title: String = "안녕하세요"
    var body: some View {
        NavigationView {
            ScrollView {
                Text(title)
            }
            .onAppear(perform: {
                DispatchQueue.main.asyncAfter(deadline: .now() + 3){
                title = "서근개발블로그"
                }
            })
            .navigationBarTitle("onAppear Bootcamp")
        }
    }
}

한번 프리뷰를 실행해보겠습니다. 저는 title이 서근개발블로그 로 바뀌는 데까지 3초의 시간이 걸리도록 해줬습니다. 확인해볼게요.

다른 예를 한번 들어보겠습니다.

 

화면에 사각형인 도형을 ForEach로 100개 정도 생성 후에 스크롤을 내릴 때마다 카운트를 시작해 현재 로드가 된 개수는 몇 개인지 나타내려고 합니다.

 

전 게시글에서도 언급했듯이 화면에 용량이 있는 데이터를 사용할 때는 단순한 Stack보다는 LazyStack을 사용하는 것이 좋습니다.

 

처음에는 VStack을 사용하고 안에 onAppear을 추가해 count += 1을 넣어줘서 카운트가 하나씩 올라가도록 해주겠습니다.

struct OnAppearBootcamp: View {
    @State var title: String = "안녕하세요"
    @State var count: Int = 0
    var body: some View {
        NavigationView {
            ScrollView {
                VStack {
                    ForEach(0..<100) { _ in
                        RoundedRectangle(cornerRadius: 20)
                            .fill(Color.white)
                            .shadow(radius: 10)
                            .frame(height: 200)
                            .onAppear {
                                count += 1
                            }
                    }
                    .padding()
                }
                Text(title)
            }
            .onAppear(perform: {
                DispatchQueue.main.asyncAfter(deadline: .now() + 3){
                title = "서근개발블로그"
                }
            })
            .navigationBarTitle("로드 된 도형 개수 : \(Int(count))개")
        }
    }
}

한번 결과하면을 볼까요?

처음 실행했을 때부터 100개가 한 번에 로드가 되었습니다. 하지만 VStackLazyVStack으로 수정해준다면 어떨까요?

        NavigationView {
            ScrollView {
                LazyVStack {
                    ForEach(0..<100) { _ in
                        RoundedRectangle(cornerRadius: 20)
                            .fill(Color.white)
                            .shadow(radius: 10)
                            .frame(height: 200)
                            .onAppear {
                                count += 1
                            }
                    }
                    .padding()
                }
                Text(title)
            }
            .onAppear(perform: {
                DispatchQueue.main.asyncAfter(deadline: .now() + 3){
                title = "서근개발블로그"
                }
            })
            .navigationBarTitle("로드 된 도형 개수 : \(Int(count))개")
        }

 

읽어주셔서 감사합니다🤟