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

SwiftUI中Firebase推送通知:APP关闭时获取内容并存入UserDefaults

解决SwiftUI中Firebase推送通知在App关闭时无法获取数据的问题

你的问题核心在于App完全关闭状态下,推送通知的触发逻辑和前台/后台活跃状态完全不同——你原来使用的didReceiveRemoteNotification方法仅在App前台运行或后台挂起时生效,App关闭时根本不会触发这个方法。要覆盖所有场景并把推送数据存入UserDefaults,需要做以下调整:

1. 补充UNUserNotificationCenter代理实现

必须让AppDelegate遵守UNUserNotificationCenterDelegate协议,才能捕获到App关闭时用户点击通知的事件,以及推送到达时的全场景处理逻辑。

2. 覆盖三种推送场景

  • App前台运行:通过通知代理的willPresent方法处理
  • App后台挂起/关闭状态,用户点击通知启动:通过通知代理的didReceive方法和启动参数launchOptions处理

修改后的完整代码

class AppDelegate: NSObject, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()
        Messaging.messaging().delegate = self
        
        // 设置通知中心代理
        UNUserNotificationCenter.current().delegate = self
        
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { isOn, _ in
            print(isOn)
            guard isOn else { return }
        }
        application.registerForRemoteNotifications()
        
        // 处理App从关闭状态被推送通知直接启动的情况
        if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable: Any] {
            saveNotificationToUserDefaults(userInfo: remoteNotification)
        }
        
        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }

    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        if let token = fcmToken {
            print(token)
        }
    }

    // 处理App前台收到推送的情况(iOS 10+)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        saveNotificationToUserDefaults(userInfo: userInfo)
        // 前台显示通知的样式配置
        completionHandler([.alert, .sound, .badge])
    }

    // 处理用户点击推送通知的情况(后台/关闭状态启动App)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        saveNotificationToUserDefaults(userInfo: userInfo)
        completionHandler()
    }

    // 通用方法:解析推送数据并存入UserDefaults
    private func saveNotificationToUserDefaults(userInfo: [AnyHashable: Any]) {
        print("推送数据:", userInfo)
        
        guard let type = userInfo["type"] as? String,
              let aps = userInfo["aps"] as? [String: Any],
              let alert = aps["alert"] as? [String: Any],
              let body = alert["body"] as? String,
              let title = alert["title"] as? String else {
            print("解析推送数据失败")
            return
        }
        
        print("通知类型:", type)
        print("通知内容(body):", body)
        print("通知标题(title):", title)
        
        // 读取已保存的通知列表
        var notifications = UserDefaults.standard.array(forKey: "notifications") as? [[String: String]] ?? []
        // 组装新通知数据
        let notificationData: [String: String] = ["type": type, "body": body, "title": title]
        // 添加并保存
        notifications.append(notificationData)
        UserDefaults.standard.set(notifications, forKey: "notifications")
        // iOS 10+后系统会自动同步UserDefaults,特殊场景才需要手动调用synchronize
        // UserDefaults.standard.synchronize()
    }
}

关键说明

  • 把重复的解析和保存逻辑抽成通用方法,避免代码冗余
  • 通过UNUserNotificationCenterDelegate的两个方法覆盖了前台显示通知、用户点击通知的所有场景
  • 在didFinishLaunchingWithOptions中处理了App完全关闭时,用户点击通知直接启动App的场景——此时推送数据会被包含在启动参数里

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:02:41