You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NavigationSplitView中用navigationDestination实现跨视图跳转?

适配macOS/iOS 16的NavigationSplitView跨视图导航解决方案

问题背景

正在开发适配macOS、iOS 16的通用App,采用NavigationSplitView实现双栏布局:

  • 侧边栏包含两个绑定NavigationOption类型的NavigationLink,通过.navigationDestination(for: NavigationOption.self)加载对应的VendorsView和TransactionsView
  • VendorsView展示供应商列表,列表项是绑定Vendor类型的NavigationLink,需要跳转到带指定Vendor的TransactionsView
  • 当前遇到的问题:
    1. iOS端无法从VendorsView跳转到指定Vendor的TransactionsView,提示找不到匹配的navigationDestination(macOS端生效)
    2. 代码嵌套多层NavigationStack和navigationDestination,逻辑混乱
    3. macOS端跳转到TransactionsView后,侧边栏的VendorsView链接仍保持高亮,同步选中绑定时会触发额外导航

原问题代码:

struct MainView: View {
var body: some View {
        NavigationSplitView {
            VStack {
                // Sidebar
                List(NavigationOption.navigationOptions) { option in
                    NavigationLink(value: option) {
                        Label(option.name, systemImage: option.icon)
                    }
                }
                .navigationDestination(for: NavigationOption.self) { option in
                    NavigationStack {
                        option.viewForPage()
                            .navigationDestination(for: Vendor.self) { vendor in
                                TransactionsView(vendor: vendor)
                            }
                            .id(option.id)
                    }
                }
                .navigationDestination(for: Vendor.self) { vendor in
                    TransactionsView(vendor: vendor)
                }
    }.navigationTitle("Sidebar")

} detail: {
   NavigationStack {
      Text("select something")
   }
}

简洁可行的解决方案

通过统一管理导航目标、移除嵌套导航栈、同步选中状态这几个关键点优化,代码逻辑清晰且兼容双平台:

优化后完整代码

// 示例NavigationOption枚举(按你的实际需求调整)
enum NavigationOption: Identifiable, CaseIterable {
    case vendors, transactions
    var id: Self { self }
    var name: String {
        switch self {
        case .vendors: return "供应商"
        case .transactions: return "交易记录"
        }
    }
    var icon: String {
        switch self {
        case .vendors: return "building.2"
        case .transactions: return "list.bullet"
        }
    }
    func viewForPage() -> some View {
        switch self {
        case .vendors: return VendorsView()
        case .transactions: return TransactionsView(vendor: nil)
        }
    }
}

// 示例Vendor模型(按你的实际需求调整)
struct Vendor: Identifiable {
    let id = UUID()
    let name: String
}

// 主视图优化实现
struct MainView: View {
    @State private var selectedOption: NavigationOption?
    @State private var selectedVendor: Vendor?
    
    var body: some View {
        NavigationSplitView {
            List(NavigationOption.allCases, selection: $selectedOption) { option in
                NavigationLink(value: option) {
                    Label(option.name, systemImage: option.icon)
                }
            }
            .navigationTitle("Sidebar")
            // 统一注册NavigationOption的导航目标
            .navigationDestination(for: NavigationOption.self) { option in
                option.viewForPage()
            }
            // 统一注册Vendor的导航目标
            .navigationDestination(for: Vendor.self) { vendor in
                TransactionsView(vendor: vendor)
                    .onAppear {
                        // 同步侧边栏选中状态,解决高亮残留问题
                        selectedOption = .transactions
                    }
            }
        } detail: {
            Text("请选择一个选项")
        }
    }
}

// VendorsView简化实现
struct VendorsView: View {
    let vendors: [Vendor] = [
        Vendor(name: "供应商A"),
        Vendor(name: "供应商B")
    ]
    
    var body: some View {
        List(vendors) { vendor in
            NavigationLink(value: vendor) {
                Text(vendor.name)
            }
        }
        .navigationTitle("供应商")
    }
}

// TransactionsView实现
struct TransactionsView: View {
    let vendor: Vendor?
    
    var body: some View {
        VStack {
            if let vendor {
                Text("查看 \(vendor.name) 的交易记录")
            } else {
                Text("查看全部交易记录")
            }
        }
        .navigationTitle("交易记录")
    }
}

关键优化说明

  • 统一导航目标位置:将所有.navigationDestination注册在NavigationSplitView的侧边栏层级,iOS和macOS都能正确识别导航目标,解决iOS找不到跳转目标的问题
  • 移除嵌套NavigationStack:NavigationSplitView的详情栏本身具备导航上下文,无需在导航目标中嵌套额外的NavigationStack,简化逻辑
  • 同步侧边栏高亮状态:通过selection绑定侧边栏列表的选中项,在跳转到TransactionsView时更新选中状态为.transactions,解决macOS侧边栏高亮残留的问题
  • 简化子视图逻辑:VendorsView直接使用绑定Vendor的NavigationLink即可,无需额外嵌套导航目标,代码更简洁

内容的提问来源于stack exchange,提问作者Johannes Dorn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 06:13:12