【问题标题】:NavigationLink in List using isActive pushes the wrong row使用 isActive 的 List 中的 NavigationLink 推送错误的行
【发布时间】:2022-01-25 13:29:38
【问题描述】:

我正在尝试使用 NavigationLink 的 isActive 变量来弹回根视图控制器。

我遇到的问题是单击列表项时使用 isActive 会推送错误的行。删除 isActive 变量,一切都按预期工作。

这里有一些示例代码用于演示目的:

struct ContentView: View {
    
    @State private var activateNavigationLink: Bool = false

    var exampleData = ["a", "b", "c"]
    
    var body: some View {
        
        NavigationView {
            
            List(exampleData, id: \.self) { item in
                
                NavigationLink(
                    destination: SecondView(item: item), isActive: $activateNavigationLink) {
                    
                    Text(item)
                }
            }
        }
    }
}

第二视图

struct SecondView: View {
    
    var item: String
    
    var body: some View {
        Text(item)
    }
}

这让我发疯了。任何帮助将不胜感激。

【问题讨论】:

    标签: swift xcode swiftui


    【解决方案1】:

    因为activateNavigationLink 在您的代码中只是一个Bool,如果它是true,那么每个NavigationLink 都会在您的List 中注册为活动的。现在,这表现为每次推送的最后一项 (C)。

    相反,您需要一些系统来存储哪个项处于活动状态,然后将其转换为布尔绑定以供NavigationLink 使用。

    这是一种可能的解决方案:

    struct ContentView: View {
        
        @State private var activeNavigationLink: String? = nil
    
        var exampleData = ["a", "b", "c"]
        
        func bindingForItem(item: String) -> Binding<Bool> {
            .init {
                activeNavigationLink == item
            } set: { newValue in
                activeNavigationLink = newValue ? item : nil
            }
        }
        
        var body: some View {
            
            NavigationView {
                
                List(exampleData, id: \.self) { item in
                    
                    NavigationLink(
                        destination: SecondView(item: item), isActive: bindingForItem(item: item)) {
                        
                        Text(item)
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢@jnpdx。我不明白bindingForItem 函数是如何工作的。请给我一些更详细的信息吗?
    • 当然。绑定提供了一个 get 和一个 set。为每个项目生成不同的绑定。在获取时,它会检查活动链接是否等于项目——如果是,它返回 true,如果不是,则返回 false。设置时,如果传入值为 true,则设置项目的活动链接。如果为 false,则将活动链接(可选)设置为 nil。
    • 谢谢。虽然我如何在 SecondView 中以编程方式弹回根视图,但效果很好?
    • 您可以将 Binding 传递给 activeNavigationLink 到子视图,然后在要弹出时将其设置为 nil。或者,将闭包传递给父视图上将 activeNavigationLink 设置为 true 的函数。如果您需要其中任何一个,请告诉我,我可以在回到我的电脑前完成。
    【解决方案2】:

    您不应该在主视图上使用 activeNavigationLink,它应该与 cellView 一起使用

    struct ContentView: View {
            
        var exampleData = ["a", "b", "c"]
        
        var body: some View {
            
            NavigationView {
                
                List(exampleData, id: \.self) { item in
                    
                   CellView(item: item)
                }
            }
        }
    }
    

    单元格视图

    struct CellView: View {
            
        @State private var activateNavigationLink: Bool = false
            var item: String
            
            var body: some View {
                  NavigationLink(
                            destination: SecondView(item: item), isActive: $activateNavigationLink) {
                            
                            Text(item)
                        }
            }
        }
    

    第二视图

    struct SecondView: View {
        
        var item: String
        
        var body: some View {
            Text(item)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-21
      • 2022-08-11
      • 1970-01-01
      • 1970-01-01
      • 2021-03-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      相关资源
      最近更新 更多