SwiftUI:使用 SidebarListStyle 在 NavigationView/列表中选择 NavigationLink

ixa*_*any 4 navigationview swiftui navigationlink sidebarliststyle

我想以编程方式选择/NavigationLink中的特定内容。NavigationViewList

\n

以下代码在纵向或横向模式下的 iPhone 上都可以正常工作 == 在列表除了目标视图之外不永久可见的情况下。

\n

在此输入图像描述

\n

代码:

\n
struct ContentView: View {\n\nprivate let listItems = [ListItem(), ListItem(), ListItem()]\n@State var selection: Int? = 0\n\nvar body: some View {\n    NavigationView {\n        \n        List(listItems.indices) {\n            index in\n            \n            let item = listItems[index]\n            let isSelected = (selection ?? -1) == index\n            \n            NavigationLink(destination: Text("Destination \\(index)"),\n                           tag: index,\n                           selection: $selection) {\n                \n                Text("\\(item.name) \\(index) \\(isSelected ? "selected" : "")")\n                \n            }\n            \n        }\n    \n    }\n    .listStyle(SidebarListStyle())\n    .onAppear(perform: {\n        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {\n            selection = 2\n        })\n    })\n    }\n\n}\n\n\nstruct ListItem: Identifiable {\n    var id = UUID()\n    var name: String = "Some Item"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但它在横向模式下的 iPad 上失败:虽然导航本身可以工作(目的地显示正确),NavigationLink仍未选择。

\n

\xe2\x86\x92 如何以在 iPad 上显示的方式选择 NavigationLink?

\n

Asp*_*eri 6

这是可能的方法。这个想法是通过视图模型以编程方式激活导航链接,但将模型级选择和表示(由链接拥有)选择分开。

使用 Xcode 12b3 / iOS+iPadOS 14 进行测试。

class SelectionViewModel: ObservableObject {
    var currentRow: Int = -1 {
        didSet {
            self.selection = currentRow
        }
    }

    @Published var selection: Int? = nil
}

struct SidebarContentView: View {
@StateObject var vm = SelectionViewModel()
private let listItems = [ListItem(), ListItem(), ListItem()]

var body: some View {
    NavigationView {

        List(listItems.indices) {
            index in

            let item = listItems[index]
            let isSelected = vm.currentRow == index

            Button("\(item.name) \(index) \(isSelected ? "selected" : "")") { vm.currentRow = index }
            .background (
                NavigationLink(destination: Text("Destination \(index) selected: \(vm.currentRow)"),
                               tag: index,
                               selection: $vm.selection) {
                    EmptyView()
                }.hidden()
            )
        }

    }
    .listStyle(SidebarListStyle())
    .onAppear(perform: {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            vm.currentRow = 2
        })
    })
    }
}
Run Code Online (Sandbox Code Playgroud)