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:

登录:

info视图:

浙公网安备 33010602011771号