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

iOS 16中如何无需显式创建Link,通过NavigationStack实现自动导航?

问题分析

你遇到的问题是使用navigationDestination(isPresented:)触发导航后,视图又跳回启动动画。核心原因是你在完成API调用后同时修改了doneLoading和show两个状态变量:当doneLoading触发导航时,show被设为false导致根视图重新显示启动动画,SwiftUI的NavigationStack在这种快速状态变化下出现了导航逻辑异常。

正确实现方法

方法1:使用NavigationPath管理导航(推荐)

NavigationPath是SwiftUI中更可靠的导航管理方式,能避免isPresented绑定可能出现的状态冲突问题:

@State var show = false
@StateObject var viewModel: BumperScreenViewModel
@StateObject var sheetManager = SheetManager()
@State private var navigationPath = NavigationPath() // 新增导航路径

init(viewModel: @autoclosure @escaping () -> BumperScreenViewModel) {
    self._viewModel = .init(wrappedValue: viewModel())
}

var body: some View {
    NavigationStack(path: $navigationPath) { // 绑定NavigationPath
        VStack {
            ZStack {
                Color(.trulliGold)
                    .ignoresSafeArea()
                VStack {
                    if show {
                        Spacer()
                        loadAnimation
                            .frame(width: 150, height: 150)
                            .task {
                                try? await viewModel.getDataFromAPI()
                                try? await Task.sleep(for: Duration.seconds(1))
                                navigationPath.append(()) // 添加路径元素触发导航
                                print("Done")
                            }
                        Spacer()
                    } else {
                        launchAnimation
                    }
                }
            }
        }
        .navigationDestination(for: Void.self) { // 匹配路径元素类型
            ContentView()
                .environmentObject(sheetManager)
        }
    }
}

方法2:调整状态更新逻辑

如果坚持使用isPresented绑定,只需移除对show的修改,确保导航触发后根视图不会切换回启动动画:

修改task部分的代码:

.task {
    try? await viewModel.getDataFromAPI()
    try? await Task.sleep(for: Duration.seconds(1))
    doneLoading = true // 仅设置导航触发状态,不修改show
    print("Done")
}

保持navigationDestination的绑定逻辑不变:

NavigationStack {
    // ... 原有视图代码 ...
}
.navigationDestination(isPresented: $doneLoading) {
    ContentView()
        .environmentObject(sheetManager)
}

这样修改后,当doneLoading变为true时,NavigationStack会正确将ContentView推到栈顶,原加载动画视图会被隐藏,不会再跳回启动动画。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 22:27:23