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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 01:30:01