列表中的 SwiftUI NavigationLink 没有使用 isActive 获得正确的详细信息页面

Posted

技术标签:

【中文标题】列表中的 SwiftUI NavigationLink 没有使用 isActive 获得正确的详细信息页面【英文标题】:SwiftUI NavigationLink in the list doesn't get the right detail page with isActive 【发布时间】:2021-01-21 02:08:57 【问题描述】:

如果按任意单元格,我只想简单地从List 导航到详细信息页面。我有一个这样的列表:

当我单击单元格c 时,它会得到d 或其他。而不是这个页面。

这是我的代码:

struct ContentView: View 

    var items = ["a", "b", "c", "d"]
    @State var isCellSelected = false

    var body: some View 
        NavigationView 
            List 
                ForEach(items.indices, id: \.self)  index in

                    NavigationLink(
                        destination: Text("\(items[index])"),
                                        isActive: $isCellSelected,
                        label: 
                                    RowView(text: items[index])
                        )
                
            
        

    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    


struct RowView: View 

    var text: String
    var body: some View 
        VStack 
            Text(text)
        
    

如果我删除 isActive: $isCellSelected,那么它会按预期工作。我需要使用 isCellSelected 弹回根视图。不知道如何解决这个问题。

有什么帮助吗?谢谢!

编辑

更新删除isActive 并尝试设置selection = nil

truct DetailView: View 

    var text: String
    @Binding var isCellSelected: Int?

    var body: some View 
        VStack 
            Text(text)
            Button("Back") 
                isCellSelected = nil
               
        
    


struct ContentView: View 

    var items = ["a", "b", "c", "d"]
    @State var selectedTag: Int? = nil
    var body: some View 
        NavigationView 
            List 
                ForEach(items.indices, id: \.self)  index in

                    NavigationLink(
                        destination: DetailView(text: "\(items[index])", isCellSelected: $selectedTag),
                        tag: index,
                                                selection: $selectedTag,
                        label: 
                            RowView(text: items[index])
                        )
                
            
        

    

当按下Back按钮时,不返回。

【问题讨论】:

带有tag 的变体适用于 Xcode 12.1 / ios 14.1。你用的是哪个版本? @Asperi Xcode 12.3 / iOS 14.3 模拟器。 【参考方案1】:

不建议在多个NavigationLinks 之间共享一个isActive 状态。

为什么不使用selection 而不是isActive

struct ContentView: View 
    
    var items = ["a", "b", "c", "d"]
    @State var selectedTag: Int? = nil //<-
    
    var body: some View 
        NavigationView 
            List 
                ForEach(items.indices, id: \.self)  index in
                    
                    NavigationLink(
                        destination: Text("\(items[index])"),
                        tag: index, //<-
                        selection: $selectedTag, //<-
                        label: 
                            RowView(text: items[index])
                        )
                
            
        
        
    

您可以将nil 设置为selectedTag 以弹回。 似乎List 中的NavigationLink 不像我预期的那样工作。搜索解决方法并在找到时进行更新。


一个肮脏的解决方法:

(使用 Xcode 12.3/iPhone 模拟器 14.3 测试。请不要指望这适用于其他版本的 iOS,包括未来版本。)

struct DetailView: View 

    var text: String
    @Binding var isCellSelected: Bool

    var body: some View 
        VStack 
            Text(text)
            Button("Back") 
                isCellSelected = false
            
        
    

struct Item 
    var text: String
    var isActive: Bool = false

struct ContentView: View 

    @State var items = ["a", "b", "c", "d"].map Item(text: $0)
    @State var listId: Bool = false //<-

    var body: some View 
//        Text(items.description) // for debugging
        NavigationView 
            List 
                ForEach(items.indices)  index in
                    NavigationLink(
                        destination:
                            DetailView(text: "\(items[index].text)",
                                       isCellSelected: $items[index].isActive)
                            .onAppear listId.toggle()  //<-
                        ,
                        isActive: $items[index].isActive,
                        label: 
                            RowView(text: items[index].text)
                        )

                
            
            .id(listId) //<-
        
    


另一种解决方法:

struct DetailView: View 

    var text: String
    @Binding var isCellSelected: Int?

    var body: some View 
        VStack 
            Text(text)
            Button("Back") 
                isCellSelected = nil
            
        
    

struct ContentView: View 

    var items = ["a", "b", "c", "d"]
    @State var selectedTag: Int? = nil

    var body: some View 
        NavigationView 
            ZStack 
                ForEach(items.indices)  index in
                    NavigationLink(
                        destination:
                            DetailView(text: "\(items[index])",
                                       isCellSelected: $selectedTag),
                        tag: index,
                        selection: $selectedTag,
                        label: 
                            EmptyView()
                        )
                
                List 
                    ForEach(items.indices)  index in
                        Button(action: 
                            selectedTag = index
                        ) 
                            HStack 
                                RowView(text: items[index])
                                Spacer()
                                Image(systemName: "chevron.right")
                                    .foregroundColor(Color.secondary)
                            
                        
                    
                
            
        
    

【讨论】:

嗨@OOper,我累了在详细页面中按下按钮时设置selectedTag = nil,但它没有弹出,我编辑了我的问题,你能帮忙检查一下吗?谢谢。 @WilliamHu,你是对的。现在检查发生了什么。

以上是关于列表中的 SwiftUI NavigationLink 没有使用 isActive 获得正确的详细信息页面的主要内容,如果未能解决你的问题,请参考以下文章

恢复列表 SwiftUI 中的底部填充

为啥单击 SwiftUI 中的列表项后列表视图项变为灰色?

Xcode Playground 中的 SwiftUI 列表

SwiftUI:无法删除列表中的行

swiftui 列表部分中的圆角

SwiftUI:删除列表中的动画?