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

如何用最新API替代已废弃的NavigationView实现苹果设备布局?

重构方案:统一适配的SwiftUI布局实现

我之前通过horizontalSizeClass分别实现了iPhone和iPad的布局,使用了已废弃的NavigationView和NavigationLink。现在改用最新SwiftUI API实现相同效果,无需分开编写两种布局,同时支持最多6级深度导航。以下是重构后的完整代码:


1. 统一的主视图(无需区分尺寸类)

直接利用NavigationSplitView和NavigationStack的自动适配能力,不再需要单独处理iPhone/iPad入口:

struct ContentView: View {
    @State private var selectedTab: AppItem = .welcome
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        TabView(selection: $selectedTab) {
            Welcome()
                .tabItem { Label("Welcome", systemImage: "square") }
                .tag(AppItem.welcome)
            
            Profile()
                .tabItem { Label("Profile", systemImage: "triangle") }
                .tag(AppItem.profile)
            
            NavigationSplitView {
                SidebarView(navigationPath: $navigationPath)
            } detail: {
                NavigationStack(path: $navigationPath) {
                    FoobarOverview()
                        .navigationDestination(for: AppItem.self) { item in
                            item.destination
                        }
                        .navigationDestination(for: String.self) { title in
                            Detail(title: title)
                        }
                }
            }
            .tabItem { Label("Overview", systemImage: "circle") }
            .tag(AppItem.foobar)
        }
    }
}

2. 优化后的导航项枚举

简化嵌套逻辑,统一数据源,确保所有可导航项支持哈希识别:

indirect enum AppItem: Hashable, Identifiable {
    var id: Int { hashValue }
    
    case foobar, profile, welcome, articles, books, websites
    
    @ViewBuilder
    var destination: some View {
        switch self {
        case .foobar: FoobarOverview()
        case .profile: Profile()
        case .welcome: Welcome()
        case .articles: Overview(navTitle: "Articles")
        case .books: Overview(navTitle: "Books")
        case .websites: Overview(navTitle: "Websites")
        }
    }
    
    var name: String {
        switch self {
        case .foobar: return "Foobar"
        case .profile: return "Profile"
        case .welcome: return "Welcome"
        case .articles: return "Articles"
        case .books: return "Books"
        case .websites: return "Websites"
        }
    }
    
    static var sidebarItems: [AppItem] = [.welcome, .profile, .foobar]
    static var foobarSubItems: [AppItem] = [.articles, .books, .websites]
}

3. 通用侧边栏视图

自动适配紧凑/常规尺寸类,在iPhone上转为导航栈列表,在iPad上显示为侧边栏:

struct SidebarView: View {
    @Binding var navigationPath: NavigationPath
    
    var body: some View {
        List {
            ForEach(AppItem.sidebarItems) { item in
                NavigationLink(value: item) {
                    Text(item.name)
                }
            }
            
            Section("Foobar") {
                ForEach(AppItem.foobarSubItems) { item in
                    NavigationLink(value: item) {
                        Text(item.name)
                    }
                }
            }
        }
        .listStyle(.sidebar)
    }
}

4. 更新导航视图(适配新API)

将旧版NavigationLink替换为值绑定形式,支持多级路径导航:

struct FoobarOverview: View {
    var body: some View {
        List {
            ForEach(AppItem.foobarSubItems) { item in
                NavigationLink(value: item) {
                    Text(item.name)
                }
            }
        }
        .navigationTitle("Foobar")
    }
}

struct Overview: View {
    var navTitle: String
    
    var body: some View {
        List {
            ForEach(0...10, id: \.self) { num in
                let detailTitle = "\(navTitle) number: \(num)"
                NavigationLink(value: detailTitle) {
                    Text(detailTitle)
                }
            }
        }
        .navigationTitle(navTitle)
    }
}

5. 保留原有基础视图

struct Profile: View {
    var body: some View {
        Text("Profile")
            .navigationTitle("Profile")
    }
}

struct Welcome: View {
    var body: some View {
        Text("Welcome")
            .navigationTitle("Welcome")
    }
}

struct Detail: View {
    var title: String
    
    var body: some View {
        Text(title)
            .navigationTitle(title)
    }
}

核心优化说明

  • 自动适配布局:NavigationSplitView在常规尺寸类(iPad)显示多列布局,紧凑尺寸类(iPhone)自动转为堆叠导航栈,无需手动判断horizontalSizeClass
  • 多级导航支持:NavigationPath可存储任意哈希类型的导航节点,轻松支持6级以上深度导航
  • 统一数据源:不再区分iPhone/iPad的不同导航数组,通过组件自动适配显示逻辑
  • 使用最新API:替换已废弃的NavigationView和旧版NavigationLink,采用NavigationStack+navigationDestination的现代导航模式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:14:54