在美食车应用程序Apple Food Truck App中,Content View有一个指向iPadOS的NavigationSplitView.

        NavigationSplitView {
            Sidebar(selection: $selection)
        } detail: {
            NavigationStack(path: $path) {
                DetailColumn(selection: $selection, model: model)
            }
        }
...

我想要更改这一点,以删除NavigationSplitView,使其仅针对iOS.大概是这样的:

        NavigationStack(path: $path) {
            Sidebar(selection: $selection)
                .navigationDestination(for: Panel.self) { panel in
                    DetailColumn(selection: $selection, model: model)
            }
        }


...

这有几个问题--第一个问题是没有导航.通过删除Sidecar()中的$SELECTION修复此问题.第二个问题是,当应用程序导航时,它只能导航到".truck".要解决这个问题,我必须进入DetailColumn,将 Select 更改为@State,并将上面的代码更改为:

        NavigationStack(path: $path) {
            Sidebar(selection: $selection)
                .navigationDestination(for: Panel.self) { panel in
                    DetailColumn(selection: panel, model: model)
            }
        }
...

尽管这很有效,但Xcode确实抱怨说,"在堆栈的前面声明了"Food_Truck.Panel"的NavigationDestination.只会使用声明的最接近堆栈根视图的目的地."

我认为我对如何处理这一点缺乏一些理解,或者这款应用的设计是为了让它与NavigationSplitView一起工作,而不是直接与NavigationStackView一起工作.

先谢谢你.

推荐答案

我不太理解你所做的改变,但我也做了类似的改变,而且这款应用也能用.

首先,删除Sidebar中的选定内容.Sidebar不应该再拥有selection属性.您应该只使用无参数的List初始化器.

struct Sidebar: View {
    var body: some View {
        List {
            NavigationLink(value: Panel.truck) {
                Label("Truck", systemImage: "box.truck")
            }
            
            NavigationLink(value: Panel.orders) {
                Label("Orders", systemImage: "shippingbox")
            }
            ...

然后你甚至可以在ContentView中摆脱selection状态.

接下来,DetailColumn中的selection不再需要是Binding.它只是用来确定要显示哪个细节视图,而DetailColumn根本不会改变它,因此它可以是let.

struct DetailColumn: View {
    let selection: Panel?
    @ObservedObject var model: FoodTruckModel
    @State var timeframe: Timeframe = .today
    var body: some View {
        switch selection ?? .truck {
        case .truck:
            TruckView(model: model) // TruckView no longer needs to take the selection
         ...

请注意,TruckView不需要采用$selection绑定.TruckView只在cardNavigation计算(computed)属性中使用它.这个属性只是决定如何导航.注意,在iPhone上,它总是返回.navigationLink.所以你可以把它改成:

var cardNavigation: TruckCardHeaderNavigation {
    .navigationLink
}

并删除@Binding var navigationSelection: Panel?.

最后,ContentView中的代码如下所示:

NavigationStack(path: $path) {
    Sidebar()
        .navigationDestination(for: Panel.self) { panel in
            DetailColumn(selection: panel, model: model)
    }
}

Swift相关问答推荐

为什么我的引用类型对象在初始化后有3个强引用?

如何获取SCNCamera正在查看的网格点(SCNNode)的局部坐标和局部法线?

ARRaycast Query和前置摄像头(ARFaceTrackingConfiguration)

我正在try 通过代码设置节中页眉和页脚的高度,但它不起作用

从Firebase播放音频文件不起作用

物理主体未与 spritekit Swift 的网格图案上的纹理图像对齐

在Swift中如何用变量计算0.9的立方

在 Swift 5.7 中使用协议作为类型时什么时候需要写 `any`

如何返回一个通过 SwiftUI 中的另一个协议间接继承 View 协议的 struct ?

为什么 SwiftUI 中 ForEach 的这个 Select 不起作用?

Swift // Sprite Kit:类别位掩码限制

使用 Async-Await 和 Vapor-Fluent 创建 CRUD 函数 - Swift 5.6

如何删除 macOS 中的所有命令?

MainActor 隔离可变存储属性为何会出现可发送错误?

我如何从 UIAlertController 导航到新屏幕(swiftUI)

如何让 SwiftUI 中的文本在旋转框架的同时侧向显示?

在 Swift 4 中实现自定义解码器

Swift 中惰性 var 的优势是什么

Swift 3:日期与 NSDate?

保持窗口始终在顶部?