SwiftUI:如果在 ForEach 中使用 NavigationLink 会立即弹出

Posted

技术标签:

【中文标题】SwiftUI:如果在 ForEach 中使用 NavigationLink 会立即弹出【英文标题】:SwiftUI: NavigationLink pops immediately if used within ForEach 【发布时间】:2019-10-09 11:16:03 【问题描述】:

我在 List 中的 ForEach 内使用 NavigationLink 来构建一个基本的按钮列表,每个按钮都通向一个单独的详细信息屏幕。

当我点击任何列表单元格时,它会转换到该单元格的详细视图,但随后会立即弹回主菜单屏幕。

不使用 ForEach 有助于避免这种行为,但不是所希望的。

以下是相关代码:

struct MainMenuView: View 

    ...

    private let menuItems: [MainMenuItem] = [
        MainMenuItem(type: .type1),
        MainMenuItem(type: .type2),
        MainMenuItem(type: .typeN),
    ]

    var body: some View 
        List 
            ForEach(menuItems)  item in
                NavigationLink(destination: self.destination(item.destination)) 
                    MainMenuCell(menuItem: item)
                
            
        
    

    // Constructs destination views for the navigation link
    private func destination(_ destination: ScreenDestination) -> AnyView 
        switch destination 
        case .type1:
            return factory.makeType1Screen()
        case .type2:
            return factory.makeType2Screen()
        case .typeN:
            return factory.makeTypeNScreen()
        
    

【问题讨论】:

MainMenuItemIdentifiable 的一致性如何?我有一个类似的问题,一致性是隐式的。 只需包含从 UUID().uuidString 派生的每个此类菜单项的“id”属性。 当您导航到目的地时它们是否会发生变化。我的意思是,如果你在MainMenuView 中有@State@Binding@ObservedObject,身体本身会重新生成,这会导致NavigationLink 失效 完全有道理,谢谢! PS:您想将此作为答案发布,以便我接受吗? 我也面临这个问题。但是在我的情况下,我有一个基本的 foreach 包装器和导航链接,但自动弹出仍然会发生。代码在这里:ForEach(modelA) eachModel in NavigationLink(destination: Text("Detail view here")) Text("Press here to go to detail view") 。 A 型符合Identifiable 并具有id = UUID() 【参考方案1】:

如果您在MainMenuView 中有@State@Binding@ObservedObject,则会重新生成主体本身(再次计算menuItems),这会导致NavigationLink 无效(实际上是id改变就是这样做的)。因此,您不得在详细视图中修改menuItems 数组id-s。

如果每次都生成它们,请考虑设置一个常量 id 或存储在非修改部分中,例如在视图模型中。

【讨论】:

确实,被覆盖的“id”属性值是从“UUID().uuidString”派生的,导致了这种行为。 你的意思是id? :) 在我的例子中,每个 menuItems 的元素都有唯一的 id 并且没有自动生成,但问题仍然存在。 ``` struct DataType: Identifiable let id = UUID() var i: Int @State var dataTypes: [DataType] = return (0...99).map return DataType(i: $0) ( ) ``` 刚才看了一下。是的,当`@StateObject` 和它里面的属性被重新计算时,导航会自动弹出它。正如标准文档所暗示的那样,我们必须在 .onAppear 闭包上获取数据。由于数据已经存在于希望显示详细视图的父视图中,因此防止重复网络调用的最佳解决方法是什么? @Ravi 你找到解决这个问题的方法了吗?【参考方案2】:

也许我找到了这个错误的原因......

如果您使用 ios 15(未找到 iOS 14), 然后编写代码 NavigationLink 以转到项目中不同位置的相同视图,然后出现此错误。

所以我只是制作了另一个具有不同目标视图名称但内容相同的视图......然后它就可以工作了......

你可以试试……

对不起我的英语不好......

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于SwiftUI:如果在 ForEach 中使用 NavigationLink 会立即弹出的主要内容,如果未能解决你的问题,请参考以下文章

如何限制 ForEach 在 SwiftUI 中显示一组项目?

在 SwiftUI 中的 ForEach 中绑定

在 SwiftUI 中修改 ForEach 内的视图

SwiftUI 将几何阅读器与 ForEach 结合使用

使用 ForEach (SwiftUI) 的偶数行和奇数行

SwiftUI 列表未使用 ForEach 正确更新