iOS 18 SwiftUI导航异常:返回时跳过PageTwo页面问题排查
问题原因与解决方案
核心问题
你遇到的返回跳过PageTwo的问题,本质是单一导航状态变量的设计导致导航栈被重置。当你通过Alert直接将导航状态设置为PageThree时,navigationDestination会直接替换当前的导航栈,而非在PageTwo的栈顶push新页面,所以返回时自然会跳过PageTwo回到根视图ContentView。
解决方案:改用导航栈数组维护页面层级
放弃单一的currentPage式状态,改用数组维护完整的导航栈,让NavigationStack直接绑定这个数组,所有跳转操作都通过修改数组的append/removeLast实现,保证导航栈的层级正确。
步骤1:重构AppState的导航状态
enum PageType: Hashable { case contentView case pageTwo case pageThree } class AppState: ObservableObject { @Published var navigationStack: [PageType] = [.contentView] // 初始化根页面 @Published var showTimerAlert = false // 定时器结束的弹窗状态 }
步骤2:调整NavigationStack的绑定与navigationDestination
在MenuView中,将NavigationStack直接绑定到navigationStack数组,并根据数组元素匹配对应页面:
struct MenuView: View { @EnvironmentObject var appState: AppState var body: some View { NavigationStack(path: $appState.navigationStack) { TabView { Tab("首页", systemImage: "house") { ContentView() } // 其他Tab内容... } .navigationDestination(for: PageType.self) { page in switch page { case .contentView: ContentView() case .pageTwo: PageTwo() case .pageThree: PageThree() } } .alert("定时器结束", isPresented: $appState.showTimerAlert) { Button("GO") { // 在当前栈顶添加PageThree,而非替换整个状态 appState.navigationStack.append(.pageThree) } } } } }
步骤3:修改各页面的跳转逻辑
- ContentView跳转到PageTwo:
struct ContentView: View { @EnvironmentObject var appState: AppState var body: some View { Button("去PageTwo") { appState.navigationStack.append(.pageTwo) } // 异步场景下的跳转 .task { try? await Task.sleep(nanoseconds: 1_000_000_000) appState.navigationStack.append(.pageTwo) } } }
- PageTwo跳转到PageThree并启动定时器:
struct PageTwo: View { @EnvironmentObject var appState: AppState @State private var timer: Timer? var body: some View { Button("去PageThree") { appState.navigationStack.append(.pageThree) startTimer() } } private func startTimer() { timer?.invalidate() timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { _ in appState.showTimerAlert = true } } }
为什么这样能解决问题
通过数组维护导航栈,每次跳转都是向数组末尾添加新页面,导航栈的层级(ContentView → PageTwo → PageThree)会被完整保留。当从Alert点击GO跳转时,是在当前栈顶(此时栈为[.contentView, .pageTwo])添加.pageThree,变成[.contentView, .pageTwo, .pageThree],返回时依次移除最后一个元素,自然会回到PageTwo,再回到ContentView。
内容的提问来源于stack exchange,提问作者PW1990
相关产品推荐
相关产品推荐

