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
相关产品推荐
相关产品推荐

