Root-> A ->B -> C page, 当前C page, 如何返回B,又如何直接返回A page呢

在 SwiftUI 中,从 C 页面返回到 B 或直接返回到 A 页面有多种方式。以下是具体的实现方法:

基本设置

swift 复制代码
enum Route: Hashable {
    case a
    case b
    case c
}

struct ContentView: View {
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            AView()
                .navigationDestination(for: Route.self) { route in
                    switch route {
                    case .a:
                        AView()
                    case .b:
                        BView()
                    case .c:
                        CView()
                    }
                }
        }
        .environment(\.navigationPath, $navigationPath)
    }
}

2. 从 C 返回 B,或直接返回 A

使用环境变量传递导航控制

swift 复制代码
// 定义环境Key
struct NavigationPathKey: EnvironmentKey {
    static let defaultValue: Binding<NavigationPath>? = nil
}

extension EnvironmentValues {
    var navigationPath: Binding<NavigationPath>? {
        get { self[NavigationPathKey.self] }
        set { self[NavigationPathKey.self] = newValue }
    }
}

// A 页面
struct AView: View {
    @Environment(\.navigationPath) private var navigationPath
    
    var body: some View {
        VStack {
            Text("A 页面")
            
            Button("前往 B 页面") {
                navigationPath?.wrappedValue.append(Route.b)
            }
            .padding()
        }
        .navigationTitle("A 页面")
    }
}

// B 页面
struct BView: View {
    @Environment(\.navigationPath) private var navigationPath
    
    var body: some View {
        VStack {
            Text("B 页面")
            
            Button("前往 C 页面") {
                navigationPath?.wrappedValue.append(Route.c)
            }
            .padding()
        }
        .navigationTitle("B 页面")
    }
}

// C 页面 - 关键部分
struct CView: View {
    @Environment(\.navigationPath) private var navigationPath
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        VStack(spacing: 20) {
            Text("C 页面")
            
            // 方法1: 返回上一页 (B)
            Button("返回上一页 (B)") {
                dismiss() // 或者 navigationPath?.wrappedValue.removeLast()
            }
            
            // 方法2: 直接返回 A 页面
            Button("直接返回 A 页面") {
                // 移除最后2个页面 (C 和 B)
                navigationPath?.wrappedValue.removeLast(2)
            }
            
            // 方法3: 返回根页面 (A)
            Button("返回根页面 (A)") {
                // 移除所有页面,回到根
                navigationPath?.wrappedValue.removeLast(navigationPath?.wrappedValue.count ?? 0)
            }
            
            // 方法4: 特定路径跳转
            Button("跳转到 A 页面") {
                // 清空路径,然后添加 A
                navigationPath?.wrappedValue = NavigationPath()
                navigationPath?.wrappedValue.append(Route.a)
            }
        }
        .navigationTitle("C 页面")
    }
}

3. 使用导航管理器 (推荐)

创建导航管理器

swift 复制代码
class NavigationManager: ObservableObject {
    @Published var path = NavigationPath()
    
    // 返回上一页
    func goBack() {
        guard !path.isEmpty else { return }
        path.removeLast()
    }
    
    // 返回到特定页面
    func goBackToA() {
        // 假设路径是 [B, C],移除最后2个
        if path.count >= 2 {
            path.removeLast(2)
        }
    }
    
    // 返回到根页面
    func goToRoot() {
        path.removeLast(path.count)
    }
    
    // 导航到特定页面
    func navigateTo(_ route: Route) {
        path.append(route)
    }
}

在视图中使用

swift 复制代码
struct AppView: View {
    @StateObject private var navManager = NavigationManager()
    
    var body: some View {
        NavigationStack(path: $navManager.path) {
            AView()
                .navigationDestination(for: Route.self) { route in
                    switch route {
                    case .a: AView()
                    case .b: BView()
                    case .c: CView()
                    }
                }
        }
        .environmentObject(navManager)
    }
}

// C 页面使用导航管理器
struct CView: View {
    @EnvironmentObject private var navManager: NavigationManager
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        VStack(spacing: 20) {
            Text("C 页面")
            
            Button("返回上一页 (B)") {
                navManager.goBack()
            }
            .buttonStyle(.bordered)
            
            Button("直接返回 A 页面") {
                navManager.goBackToA()
            }
            .buttonStyle(.borderedProminent)
            
            Button("返回根页面") {
                navManager.goToRoot()
            }
            .buttonStyle(.bordered)
            
            // 当前路径信息
            Text("当前导航栈深度: \(navManager.path.count)")
        }
        .navigationTitle("C 页面")
        .navigationBarBackButtonHidden(true) // 隐藏默认返回按钮
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                Button("返回") {
                    navManager.goBack()
                }
            }
        }
    }
}

4. 使用 @Binding 传递控制 (简单场景)

swift 复制代码
struct CView: View {
    @Binding var path: NavigationPath
    
    var body: some View {
        VStack {
            Text("C 页面")
            
            Button("返回 B") {
                path.removeLast()
            }
            
            Button("返回 A") {
                // 移除 B 和 C
                if path.count >= 2 {
                    path.removeLast(2)
                }
            }
        }
    }
}

总结

从 C 返回 B 的方法:

  • dismiss() - 最简单的返回上一页
  • navigationPath.removeLast() - 编程式返回
  • navManager.goBack() - 通过管理器返回

从 C 直接返回 A 的方法:

  • navigationPath.removeLast(2) - 移除最后2个页面
  • navigationPath.removeLast(navigationPath.count) - 清空所有页面
  • navManager.goBackToA() - 通过管理器精确控制

推荐使用导航管理器的方式,因为它提供了更好的代码组织和可维护性。

相关推荐
旧梦吟4 分钟前
脚本网页 linux内核源码讲解
linux·前端·stm32·算法·html5
李少兄1 小时前
深入理解 CSS :not() 否定伪类选择器
前端·css
程序员码歌8 小时前
短思考第261天,浪费时间的十个低效行为,看看你中了几个?
前端·ai编程
Swift社区8 小时前
React Navigation 生命周期完整心智模型
前端·react.js·前端框架
若梦plus8 小时前
从微信公众号&小程序的SDK剖析JSBridge
前端
用泥种荷花9 小时前
Python环境安装
前端
Light609 小时前
性能提升 60%:前端性能优化终极指南
前端·性能优化·图片压缩·渲染优化·按需拆包·边缘缓存·ai 自动化
Jimmy9 小时前
年终总结 - 2025 故事集
前端·后端·程序员
烛阴9 小时前
C# 正则表达式(2):Regex 基础语法与常用 API 全解析
前端·正则表达式·c#