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

iOS16+:Button结合NavigationStack调用NavigationLink的非废弃实现

迁移至iOS16+ NavigationStack实现导航前完成任务的跳转

核心思路

废弃的tag:selection:式NavigationLink可以用NavigationStack的路径绑定替代,通过先执行任务再更新导航路径的方式,确保任务完成后再触发跳转。推荐用枚举定义导航目的地,比原代码的字符串tag更安全、易维护。

完整迁移代码

// 定义枚举明确所有导航目的地,需遵循Hashable协议
enum NavigationDestination: Hashable {
    case view1
    case notView1
}

struct ContentView: View {
    // 用数组管理导航路径,替代原有的selection变量
    @State private var path: [NavigationDestination] = []
    
    var body: some View {
        NavigationStack(path: $path) {
            VStack(spacing: 20) {
                Button("先执行任务再跳转到View1") {
                    // 执行耗时任务(示例为同步sleep,实际建议用异步操作)
                    mySleepFunctionToSleepOneSecond()
                    // 任务完成后,往路径数组添加目的地,触发导航
                    path.append(.view1)
                }
                
                Button("立即跳转到NotView1") {
                    // 直接添加目的地触发跳转
                    path.append(.notView1)
                }
            }
            .navigationTitle("Navigation")
            // 绑定枚举值与对应目标视图
            .navigationDestination(for: NavigationDestination.self) { destination in
                switch destination {
                case .view1:
                    View1()
                case .notView1:
                    NotView1()
                }
            }
        }
    }
    
    // 示例耗时函数
    private func mySleepFunctionToSleepOneSecond() {
        Thread.sleep(forTimeInterval: 1)
    }
}

// 示例目标视图(需自行实现业务逻辑)
struct View1: View {
    var body: some View {
        Text("View1")
            .navigationTitle("View1")
    }
}

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

关键说明

  1. 枚举管理目的地:用Hashable枚举替代字符串tag,避免拼写错误,同时让导航逻辑更直观
  2. 路径绑定机制:NavigationStack(path: $path)通过绑定数组管理导航栈,向数组添加元素即触发对应跳转
  3. 目的地映射:.navigationDestination(for:)负责将枚举值与目标视图关联,无需再写隐藏的EmptyView式NavigationLink
  4. 任务执行优先级:按钮回调内先完成所有任务,再更新path,确保导航动作在任务结束后触发,和原逻辑完全一致
  5. 异步任务处理:如果实际任务是异步操作(比如网络请求),需在主线程更新path,示例:
    Button("异步任务后跳转") {
        Task {
            // 异步执行任务
            await fetchData()
            // 回到主线程更新导航路径
            DispatchQueue.main.async {
                path.append(.view1)
            }
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:35:16