ios开发:navigationstack 跳转到需要登录的页面时,如果未登录则跳转到登录页面,登录成功后再跳转到目标页面

一,代码:

router


import SwiftUI

// 1. 定义所有可能的页面路径
enum Route: Hashable {
    case home
    case list
    case detail(item: String) // 详情页通常需要传参
    case login
    case info(userName: String)
}

// 2. 路由管理器
class Router: ObservableObject {
    @Published var path = NavigationPath()
    @Published var isLoggedIn = false // 模拟登录状态
    
    // 核心:暂存被拦截的路由(包含其所有参数)
     private var pendingRoute: Route?
     
    // 拦截器核心方法
     func push(_ route: Route) {
         switch route {
         case .info: // 如果是去个人信息页
             if !isLoggedIn {
                 // 1. 记录下当前想去的路由和参数
                 pendingRoute = route
                 // 2. 跳转到登录页
                 path.append(Route.login)
             } else {
                 path.append(route)
             }
         default:
             path.append(route)
         }
     }
    
    /*
    // 拦截器核心方法
    func push(_ route: Route) {
        // 检查目标页面是否需要登录
        if route == .info && !isLoggedIn {
            // 如果未登录且去往 info,则拦截并转到登录页
            path.append(Route.login)
        } else {
            // 否则正常跳转
            path.append(route)
        }
    }
    */
    
    // 返回根视图
    func popToRoot() {
        path.removeLast(path.count)
    }
    
    // 返回上一级
    func pop() {
        path.removeLast()
    }

    // 登录成功后的恢复逻辑
        func loginSuccess() {
            isLoggedIn = true
            // 1. 移除登录页
            path.removeLast()
            
            // 2. 检查是否有暂存的任务
            if let target = pendingRoute {
                path.append(target) // 自动跳转到目标页,参数自动带过去
                pendingRoute = nil  // 清空缓存
            }
        }
    
}

根视图:

import SwiftUI

struct ContentView2: View {
    @StateObject var router = Router() // 初始化路由

    var body: some View {
        // 绑定路径到 router.path
        NavigationStack(path: $router.path) {
            HomeView()
                .navigationDestination(for: Route.self) { route in
                    // 统一在这里分发页面跳转
                    switch route {
                    case .home:
                        HomeView()
                    case .list:
                        ListView()
                    case .detail(let item):
                        DetailView2(item: item)
                    case .login:
                        LoginView()
                    //case .info:
                    //    InfoView()
                    case .info(let name):
                        InfoView(userName: name)
                    }
                }
        }
        .environmentObject(router) // 全局注入,子视图可通过 @EnvironmentObject 获取
    }
}

home view:

import SwiftUI

// 首页 Home
struct HomeView: View {
    @EnvironmentObject var router: Router // 注入路由对象以便手动控制跳转
    
    var body: some View {
        VStack(spacing: 20) {
            Image(systemName: "house.fill").font(.largeTitle)
            Text("这是首页").font(.headline)

            List {
                 //Button("去列表页") { router.push(.list) }
                 Button(action: {
                    // 跳转前可以处理逻辑,例如检查网络
                    router.push(.list)
                 }) {
                    Text("进入列表页")
                        .frame(maxWidth: .infinity)
                 }
                 .buttonStyle(.borderedProminent)
                 .padding()
                 
                 // 这个按钮会触发拦截逻辑
                 Button("去个人信息 (需登录)") {
                     //router.push(.info)
                     router.push(.info(userName: "老王"))
                 }
             }
            
        }
        .navigationTitle("首页")
    }
}

info view:

import SwiftUI

// 个人信息页 InfoView
struct InfoView: View {
    @EnvironmentObject var router: Router

    let userName: String // 接收参数
    
    var body: some View {
        Text("正在查看 \(userName) 的私密档案")
            .navigationTitle("个人中心")
    }
}

login view:

import SwiftUI

// 登录页 LoginView
struct LoginView: View {
    @EnvironmentObject var router: Router
    
    var body: some View {
        VStack(spacing: 20) {
            Text("请先登录").font(.title)
            
            Button("点击登录") {
                // 登录成功,告诉 router 恢复刚才的操作
                router.loginSuccess()
            }
            .buttonStyle(.borderedProminent)
        }
        .navigationTitle("登录")
    }
}

 

二,测试效果:

home:

image

登录:

image

info视图:

image

 

posted @ 2026-04-07 17:16  刘宏缔的架构森林  阅读(7)  评论(0)    收藏  举报