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() - 通过管理器精确控制

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

相关推荐
pas1361 天前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
摇滚侠1 天前
2 小时快速入门 ES6 基础视频教程
前端·ecmascript·es6
珑墨1 天前
【Turbo】使用介绍
前端
军军君011 天前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three
打小就很皮...1 天前
Tesseract.js OCR 中文识别
前端·react.js·ocr
wuhen_n1 天前
JavaScript内存管理与执行上下文
前端·javascript
Hi_kenyon1 天前
理解vue中的ref
前端·javascript·vue.js
落霞的思绪1 天前
配置React和React-dom为CDN引入
前端·react.js·前端框架
Hacker_Z&Q1 天前
CSS 笔记2 (属性)
前端·css·笔记
Anastasiozzzz1 天前
LeetCode Hot100 295. 数据流的中位数 MedianFinder
java·服务器·前端