본문 바로가기
Project/SwiftUI 블록와이드

[SwiftUI Project] NavigationLink Lazy View 만들기

by iOS_woo 2022. 9. 19.

NavigationLink Lazy View

이번에는 NavigationLink Lazy Loding에 대해서 알아보겠습니다. 

 

NavigationLink로 화면전환을 할 때 아래와 같이 작성하는게 일반적인 것 같아요.

NavigationLink(
  destination: DetailView(coin: coin),
  label: { CoinRowView(coin: coin) }
)

 

struct DetailView: View {
    
    var coin: CoinModel
    
    init(coin: CoinModel) {
        self.coin = coin
        print("\(coin.name)")
    }
    
    var body: some View {
        Text(coin.name)
    }
}

 

보여지는 것으로는 문제가 없어보이지만,  print로 무슨 일이 일어나고 있는지 살펴보겠습니다. 

개선 전의 NavigationLink

DetailView를 띄우지도 않았는데 수많은 DetailView들을 init 한 것을 확인할 수 있습니다. 

이럴 경우 DetailView가 간단하지 않고 복잡하다면 성능 문제가 발생 할 것 같습니다. 

 

어떻게 개선할 수 있을까요? 

원하는 것은 유저가 View를 탭하고 진입할 때에만 init 되도록 하는 것입니다. 

 

다음과 같이 NavigationLazyView를 추가해줌으로써 해결 할 수 있습니다. 

struct NavigationLazyView<Content: View>: View {
    let build: () -> Content
    init(_ build: @autoclosure @escaping () -> Content) {
        self.build = build
    }
    var body: Content {
        build()
    }
}

 

이번 프로젝트에서 사용할 때의 코드입니다.

 ScrollView() {
            LazyVStack {
                ForEach(viewModel.allCoins) { coin in
                    NavigationLink(
                        destination: NavigationLazyView(DetailView(coin: coin)),
                        label: { CoinRowView(coin: coin) }
                    )
                }
            }
        }

 

desination에서 화면전환될 뷰를 NavigationLazyView로 한번 감싸주며 사용할 수 있습니다. 

 

다시 한번 시뮬레이터를 돌려보면.. 

개선 후의 NavigationLink

 

시뮬레이터를 다시 돌리면 이제는 유저가 탭한 DetailView만 init 되는 것을 확인할 수 있습니다! 

 

 

 

NavigationLink Lazy View 참고 자료: 

 

SwiftUI NavigationLink loads destination view immediately, without clicking

With following code: struct HomeView: View { var body: some View { NavigationView { List(dataTypes) { dataType in NavigationLink(destination: AnotherView()...

stackoverflow.com

 

NavigationLink Lazy View 참고 블로그:

 

Lazy Loading View 만들기

실제로 화면에 나타나기 전까지는 로드되지 않는 View를 만들어 봅시다!

velog.io

 

댓글