You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从AppDelegate推送SwiftUI页面 接收通知跳转指定Tab栏

实现方案

核心思路

通过回调闭包建立AppDelegate和MainApp的关联,直接复用MainApp中已初始化的rootViewModel实例,通过修改rootViewModel的状态驱动SwiftUI页面跳转和Tab切换。


代码修改

1. 改造AppDelegate

新增rootViewModel引用和通知点击回调闭包,同时实现用户点击通知的代理方法:

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    // 持有MainApp初始化的rootViewModel实例
    var rootViewModel: MainViewModel?
    // 通知点击回调,参数为通知携带的userInfo
    var onNotificationTap: (([AnyHashable: Any]) -> Void)?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // 必须设置通知中心代理,否则通知回调不生效
        UNUserNotificationCenter.current().delegate = self
        return true
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        print("willPresent notification")
        let info = notification.request.content.userInfo
        completionHandler([.badge, .sound, .banner])
    }

    // 处理用户点击通知的逻辑
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        onNotificationTap?(userInfo)
        completionHandler()
    }
}

2. 改造MainViewModel

新增控制Tab选中和登录状态的响应式属性:

class MainViewModel: ObservableObject {
    // 控制Tab选中索引,通知tab的tag可根据实际业务调整
    @Published var selectedTab: Int = 0
    // 登录状态,替换原MainApp中的本地变量
    @Published var authenticated: Bool = false
    // 其他原有业务逻辑保留
}

3. 改造MainApp

在初始化时给AppDelegate注入rootViewModel和通知点击的处理逻辑:

@main 
struct MainApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    private var rootViewModel: MainViewModel

    init() {
        let vm = MainViewModel()
        self.rootViewModel = vm
        // 给AppDelegate注入依赖
        appDelegate.rootViewModel = vm
        appDelegate.onNotificationTap = { userInfo in
            // 直接修改rootViewModel状态,驱动切换到通知tab
            // 假设通知tab对应的tag为2,按需修改为你的实际值
            vm.selectedTab = 2
            // 可在此处处理额外业务逻辑,比如根据userInfo存目标页面ID,后续跳转到对应详情页
            // 示例:vm.targetNotificationId = userInfo["notification_id"] as? String
        }
    }

    var body: some Scene {
        WindowGroup {
            if rootViewModel.authenticated {
                Tabbar()
                    .environmentObject(rootViewModel)
            } else {
                SecondScreen()
                    .environmentObject(rootViewModel)
            }
        }
    }
}

4. 改造Tabbar视图

绑定rootViewModel的selectedTab属性实现受控切换:

struct Tabbar: View {
    @EnvironmentObject var rootViewModel: MainViewModel

    var body: some View {
        TabView(selection: $rootViewModel.selectedTab) {
            // 首页tab示例
            HomeView()
                .tabItem { Label("首页", systemImage: "house") }
                .tag(0)
            // 其他tab示例
            MessageView()
                .tabItem { Label("消息", systemImage: "message") }
                .tag(1)
            // 通知tab
            NotificationView()
                .tabItem { Label("通知", systemImage: "bell") }
                .tag(2)
        }
    }
}

注意事项

  • 通知tab的tag值要和onNotificationTap中设置的selectedTab值保持一致
  • 如果需要点击通知直接跳转到通知详情页,只需在MainViewModel新增对应的@Published属性,在NotificationView中监听属性触发路由跳转即可
  • 该方案全程复用同一个rootViewModel实例,所有原有业务逻辑可直接调用,无需额外初始化

内容的提问来源于stack exchange,提问作者Muli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:09:01