简体   繁体   中英

SwiftUI Nested NavigationLink causing double transition

Running on iOS 15. When I select a NavigationLink from ItemListView , the resultant ItemView animates onto the screen twice. I've discovered two (anti)fixes to this problem:

  1. Don't use nested NavigationLinks . If I treat ItemListView as the application's primary view, bypassing NavigationTestView , and wrap the list in its own NavigationView , the views transition as expected. This is a non-starter because my application may require nesting of NavigationLinks.

  2. Don't use a navigation manager. Keeping the navigation state local to each view component and passing bindings around works as expected. This is maintenance nightmare however, and the code becomes unruly very quickly.

Is this a bug with SwiftUI and the underlying system, or am I making a mistake somewhere? If I'm making a mistake, what is it? If the problem is with SwiftUI what are some best practices to work around this issue until it is resolved?

Note that this code is adapted from code presented in this tutorial . Multiple people in the tutorial's comments also complain of this very issue.

// NavigationManager.swift

class NavigationManager: ObservableObject {
    @Published var itemListIsShown: Bool = false 
    @Published var selectedItem: String? = nil
}
// NavigationTestView.swift
// Application root view (Visually)

struct NavigationTestView: View {
    
    @EnvironmentObject var navigationManager: NavigationManager
    
    var body: some View {
        NavigationView {
            VStack {
                Text("Primary view")
                
                NavigationLink(
                    destination: ItemListView(),
                    isActive: $navigationManager.itemListIsShown) {
                        Text("Show item list")
                    }
            }
        }
    }
}
// ItemListView.swift

struct ItemListView: View {
    
    @EnvironmentObject var navigationManager: NavigationManager
    
    let items: [String] = ["🍎", "🍓", "🍉", "🥭"]
    
    var body: some View {
        List(items, id: \.self) { item in
            NavigationLink(
                destination: ItemView(item: item),
                tag: item, 
                selection: $navigationManager.selectedItem) { 
                    Text(item)
                }
        }
        .navigationTitle("Item list")
    }
}
// ItemView.swift

struct ItemView: View {
    
    @EnvironmentObject var navigationManager: NavigationManager
    
    let item: String
    
    var body: some View {
        VStack(spacing: 30) {
            Text(item)
            
            Button {
                navigationManager.selectedItem = nil
            } label: {
                Text("Deselect item")
            }
        }
    }
}

works for me when I add .navigationViewStyle(.stack) to the NavigationView

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM