首页 > 解决方案 > 列表中的 SwiftUI NavigationLink 没有使用 isActive 获得正确的详细信息页面

问题描述

我只想简单地从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按钮时,不返回。

标签: iosswiftswiftuiswiftui-navigationlink

解决方案


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

你为什么不使用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])
                        })
                }
            }
        }
        
    }
}

您可以设置nilselectedTag弹回。似乎无法按我的预期工作NavigationLinkList寻找解决方法并在找到时进行更新。


一个肮脏的解决方法:

(使用 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)
                            }
                        }
                    }
                }
            }
        }
    }
}

推荐阅读