iOS 11中UNUserNotificationCenter的didReceive未触发问题求助
看起来你的问题是iOS通知能正常显示,但点击横幅时userNotificationCenter(_:didReceive:withCompletionHandler:)方法没触发,我帮你梳理几个可能的原因和解决方案:
1. 检查UNUserNotificationCenterDelegate是否被正确设置(避免被Firebase覆盖)
你在didFinishLaunchingWithOptions里设置了center.delegate = self,但Firebase Cloud Messaging(FCM)初始化时可能会自动接管UNUserNotificationCenter的代理,导致你的自定义代理被覆盖。
解决方法:在FirebaseApp.configure()之后重新设置一次代理,确保AppDelegate能捕获通知响应事件:
FirebaseApp.configure() // 重新设置代理,防止被FCM覆盖 if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self }
另外,如果你使用了FCM的消息接收,建议同时实现MessagingDelegate,避免代理冲突:
// 先添加MessagingDelegate协议 class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, RCTBridgeDelegate, MessagingDelegate { // ... 其他代码 ... func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { // ... 其他代码 ... FirebaseApp.configure() if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self } // 设置Messaging代理 Messaging.messaging().delegate = self // ... 其他代码 ... } // 实现MessagingDelegate的方法(可选,但能避免潜在冲突) func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { print("### FCM Token: \(fcmToken ?? "")") } }
2. 调整Firebase Payload结构,避免字段冲突
你当前的payload同时包含顶层的notification字段和apns.payload字段,这会导致FCM和APNs的配置冲突——FCM会优先使用notification字段生成APNs请求,可能覆盖你自定义的apns.payload内容,甚至导致通知响应逻辑异常。
建议简化payload,只保留data和apns.payload字段,让APNs使用你完全自定义的配置:
return { data: { title, body, ...data }, android: { ttl: 3600 * 1000, notification: { icon: 'stock_ticker_update', color: '#002559' } }, apns: { payload: { aps: { alert: { title: 'NITL ACUMEN BI RFS CODA Dev Offshore', body: 'Send a Message - PN testing group' }, sound: 'default' } } }, condition };
3. 确保代理方法的完整性和时机
把UNUserNotificationCenter代理的设置移到
didFinishLaunchingWithOptions的最开头,确保在任何其他第三方库初始化前完成,避免代理被抢占:func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { // 优先设置通知代理 if #available(iOS 10.0, *) { let center = UNUserNotificationCenter.current() center.delegate = self center.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: {(grant, error) in // ... 授权逻辑 ... }) } else { // iOS 9及以下逻辑 let notificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(notificationSettings) } // 再执行其他初始化(Bridge、Firebase等) let bridge = RCTBridge(delegate: self, launchOptions: launchOptions) // ... 其他代码 ... }补充实现前台通知展示的方法(虽然你说横幅能显示,但确保前台状态下也能响应点击):
@available(iOS 10.0, *) func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { // 允许前台显示通知横幅 completionHandler([.alert, .sound, .badge]) }
4. 验证APNs Payload的有效性
排除Firebase的影响,用APNs测试工具直接发送纯APNs payload到设备:
{ "aps": { "alert": { "title": "Test Click", "body": "Click this notification to test" }, "sound": "default" }, "custom_data": "test_value" }
如果点击这个通知能触发你的didReceive方法,说明问题出在Firebase的payload构造上;如果还是没触发,继续检查AppDelegate的代理设置是否正确。
内容的提问来源于stack exchange,提问作者Hurobaki

