iOS15/Xcode13下SwiftUI无Storyboard点击推送通知跳转指定视图如何实现
SwiftUI 无Storyboard项目推送点击跳转到指定视图实现方案
核心思路是通过全局状态驱动界面跳转,替代UIKit时代直接操作视图控制器的逻辑。
步骤1:创建全局路由状态管理类
定义全局可观察的路由对象,统一控制Tab选中状态和页面导航路径:
import SwiftUI @MainActor final class AppRoute: ObservableObject { // 对应TabView的选中索引,假设消息页是第二个Tab,tag设置为1 @Published var selectedTab: Int = 0 // 若需要进入消息页后继续跳转内部子页面,可使用NavigationPath控制 @Published var messagesNavPath = NavigationPath() }
步骤2:实现AppDelegate逻辑
在通知点击回调中修改全局路由状态,完成跳转触发:
import UIKit import UserNotifications class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate { // 持有全局路由对象 var appRoute: AppRoute? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { // 设置通知中心代理 UNUserNotificationCenter.current().delegate = self return true } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { Task { @MainActor in // 切换到消息页对应的Tab appRoute?.selectedTab = 1 // 如果需要跳转到消息页内部的某个子页面,可追加对应路径 // appRoute?.messagesNavPath.append(你的消息详情数据模型) } completionHandler() } }
步骤3:App入口注入全局状态
在项目入口处初始化路由对象,同时注入到AppDelegate和视图环境中:
@main struct MyApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @StateObject private var appRoute = AppRoute() init() { // 给AppDelegate绑定全局路由对象 appDelegate.appRoute = appRoute } var body: some Scene { WindowGroup { MainTabView() .environmentObject(appRoute) } } }
步骤4:绑定TabView的选中状态
将TabView的选中属性和全局路由状态绑定,保证状态修改可以同步切换Tab:
struct MainTabView: View { @EnvironmentObject var appRoute: AppRoute var body: some View { TabView(selection: $appRoute.selectedTab) { HomeView() .tabItem { Label("首页", systemImage: "house") } .tag(0) MessagesView() .tabItem { Label("消息", systemImage: "message") } .tag(1) // 和AppRoute中切换的tag值保持一致 MineView() .tabItem { Label("我的", systemImage: "person") } .tag(2) } } }
步骤5:配置Messages视图导航(可选)
如果需要跳转到消息页内部的子页面,将导航路径和全局路由绑定即可:
struct MessagesView: View { @EnvironmentObject var appRoute: AppRoute var body: some View { NavigationStack(path: $appRoute.messagesNavPath) { List { // 消息列表业务逻辑 } .navigationTitle("消息") .navigationDestination(for: MessageDetailModel.self) { model in MessageDetailView(model: model) } } } }
注意事项
- 可在通知回调中先判断
response.actionIdentifier或者通知的userInfo字段,按需执行不同跳转逻辑,避免所有通知点击都跳转到消息页 - 如果项目最低支持iOS15及以下,使用
NavigationView时可将NavigationPath替换为对应Bool类型的绑定变量控制导航弹出
内容的提问来源于stack exchange,提问作者Flincorp
相关产品推荐
相关产品推荐

