简体   繁体   English

SwiftUI 嵌套 NavigationLink 导致双重转换

[英]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.在 iOS 15 上运行。当我 select 来自ItemListViewNavigationLink时,生成的ItemView在屏幕上动画两次。 I've discovered two (anti)fixes to this problem:我发现了这个问题的两个(反)修复:

  1. Don't use nested NavigationLinks .不要使用嵌套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.如果我将ItemListView视为应用程序的主视图,绕过NavigationTestView并将列表包装在其自己的NavigationView中,则视图会按预期转换。 This is a non-starter because my application may require nesting of NavigationLinks.这是一个非首发,因为我的应用程序可能需要嵌套 NavigationLinks。

  2. Don't use a navigation manager.不要使用导航管理器。 Keeping the navigation state local to each view component and passing bindings around works as expected.将导航 state 保持在每个视图组件的本地并按预期传递绑定。 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?这是 SwiftUI 和底层系统的错误,还是我在某处犯了错误? 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?如果问题出在 SwiftUI 上,在解决此问题之前,有哪些最佳实践可以解决?

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当我将.navigationViewStyle(.stack)添加到NavigationView时对我有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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