从通知中心打开推送致App崩溃,已杀死状态启动问题求助
解决推送唤醒App(杀死状态)的崩溃问题
看起来你遇到的是推送唤醒App时的崩溃问题,尤其是App被完全杀死的场景。结合你的代码,我来帮你梳理下问题点和修复方案:
问题分析
- iOS版本适配缺失:你目前只实现了旧的
didReceiveRemoteNotification方法,这个方法在iOS 10+系统下,当App被杀死后通过推送唤醒时并不会被触发,而是会将推送信息传入launchOptions,但你当前仅做了日志打印,没有完成必要的跳转或状态处理,可能因未初始化页面/资源导致崩溃。 - 处理时机不当:当App从杀死状态启动时,所有依赖服务(如Firebase、页面路由)需要完成初始化后再处理推送逻辑,否则容易出现空指针或未就绪的问题。
修复步骤
1. 实现iOS 10+的推送代理方法
添加UNUserNotificationCenterDelegate的两个核心方法,覆盖所有场景下的通知交互(包括用户点击通知):
extension YourAppDelegate: UNUserNotificationCenterDelegate { // App前台收到通知时触发,可自定义通知展示方式 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo NSLog("[RemoteNotification] App is active, received notification: \(userInfo)") // 根据需求设置展示选项(如弹窗、声音、角标) completionHandler([.alert, .sound]) } // 用户点击通知时触发(覆盖前台、后台、杀死状态) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo NSLog("[RemoteNotification] User tapped notification: \(userInfo)") // 统一处理通知逻辑 handleNotificationUserInfo(userInfo) completionHandler() } }
2. 完善didFinishLaunchingWithOptions的推送处理
当App从杀死状态通过推送启动时,launchOptions会携带推送信息,需确保初始化完成后再处理:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { Fabric.with([Crashlytics.self]) registerFirebase(application, launchOptions) // 处理杀死状态下的推送启动 if let remoteNotificationInfo = launchOptions?[.remoteNotification] as? [AnyHashable: Any] { NSLog("[RemoteNotification] Launched from killed state with notification: \(remoteNotificationInfo)") // 延迟0.5秒处理,确保所有初始化完成(可根据实际情况调整) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.handleNotificationUserInfo(remoteNotificationInfo) } } return true }
3. 统一推送处理逻辑
把所有场景的推送处理集中到一个方法,避免重复代码,同时确保逻辑一致性:
private func handleNotificationUserInfo(_ userInfo: [AnyHashable: Any]) { let appState = UIApplication.shared.applicationState if appState == .active { // 前台通知处理:比如弹出自定义弹窗提示用户 NSLog("[RemoteNotification] Handling foreground notification") } else { // 后台/杀死状态处理:根据推送参数跳转对应页面 NSLog("[RemoteNotification] Handling background/killed state notification") // 示例:根据推送中的target参数跳转页面 guard let targetPage = userInfo["target_page"] as? String else { return } guard let window = UIApplication.shared.windows.first, let rootNav = window.rootViewController as? UINavigationController else { return } switch targetPage { case "detail": let detailVC = DetailViewController() // 可从userInfo中传递页面所需参数 if let itemId = userInfo["item_id"] as? String { detailVC.itemId = itemId } rootNav.pushViewController(detailVC, animated: true) // 其他页面跳转逻辑... default: break } } }
4. 更新旧版本兼容代码
对于iOS 9及以下系统,didReceiveRemoteNotification仍会触发,将其逻辑也接入统一处理方法:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { NSLog("[RemoteNotification] didReceiveRemoteNotification for iOS9: \(userInfo)") handleNotificationUserInfo(userInfo) }
崩溃排查要点
- 空值检查:处理推送参数时,务必对必填字段做非空判断,避免因nil值导致崩溃。
- 资源初始化:确保跳转页面所需的所有资源(如网络请求、本地数据)已初始化完成,必要时可延迟处理。
- Firebase状态:确认
FirebaseApp.configure()在处理推送前已执行完成,避免依赖Firebase的操作出错。
内容的提问来源于stack exchange,提问作者Vladimir Fisher
相关产品推荐
相关产品推荐

