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

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

相关推荐
胡萝卜术8 小时前
从API调用到手写LRU:力扣146「LRU缓存」的哈希表+双向链表终极进化之路
前端·javascript·面试
科技道人8 小时前
记录 默认置灰/禁用 app ‘Search Engine Selector‘ 的disable按钮
开发语言·前端·javascript
天疆说8 小时前
Zotero Connector 在 Edge 里找不到桌面 Zotero(Linux / Zotero 9.0.6 / Edge 150)
linux·前端·edge
李伟_Li慢慢10 小时前
02-从硬件说起WebGL
前端·three.js
kyriewen11 小时前
看了微软几万人用AI编程的数据——效率涨24%的代价没人提
前端·ai编程·claude
2601_9637713711 小时前
How to Scale Your WordPress Store Traffic in 2026
前端·php·plugin
亿元程序员11 小时前
老板说我的3D箭头游戏用来做试玩太普通了,没人想玩,让我变点花样...
前端
李伟_Li慢慢12 小时前
01-threejs架构原理-课程简介
前端·three.js
_瑞13 小时前
深入理解 iOS 渲染原理
前端·ios
IT_陈寒13 小时前
SpringBoot自动配置失灵?你可能忘了这个关键注解
前端·人工智能·后端