iosswiftswiftui

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()) {
                    HomeViewRow(dataType: dataType)
                }
            }
        }
    }
}

What's weird, when HomeView appears, NavigationLink immediately loads the AnotherView. As a result, all AnotherView dependencies are loaded as well, even though it's not visible on the screen yet. The user has to click on the row to make it appear. My AnotherView contains a DataSource, where various things happen. The issue is that whole DataSource is loaded at this point, including some timers etc.

Am I doing something wrong..? How to handle it in such way, that AnotherView gets loaded once the user presses on that HomeViewRow?


Solution

  • Update:

    This code will be for iOS 15 and below.

    The best way I have found to combat this issue is by using a Lazy View.

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

    Then the NavigationLink would look like this. You would place the View you want to be displayed inside ()

    NavigationLink(destination: NavigationLazyView(DetailView(data: DataModel))) { Text("Item") }
    

    For iOS 16 and above use NavigationStack:

        var body: some View {
            NavigationStack {
                List(items) { item in
                    NavigationLink(item.name, value: item)
                }
                .navigationDestination(for: DataModel.self) { item in
                    DetailView(data: item)
                }
                .navigationTitle("Items")
            }
        }