iOS端Firebase通知异常:后端推送仅控制台显示无弹窗问题
解决iOS FCM后端发送主题通知不弹窗问题
看起来你遇到了FCM推送的常见问题:Firebase控制台发送的通知能正常弹窗,但后端发送的只有日志输出却没有通知提醒。这大概率是后端推送的消息格式不符合APNS要求导致的,下面给你一步步排查和解决的方案:
1. 核心原因:FCM消息类型差异
FCM有两种主要消息类型:
- Notification消息:由FCM直接传递给APNS,iOS系统会自动处理弹窗、声音和角标,不管App是前台还是后台状态(前台需要额外配置)。Firebase控制台发送的就是这种类型。
- Data消息:仅作为数据传递给App,系统不会自动展示通知,需要App自己处理展示逻辑。如果你的后端只发送了Data消息,就只会在Xcode控制台看到日志,不会有弹窗。
2. 修复后端推送格式
确保你的后端发送的请求包含notification字段,示例JSON结构如下:
{ "to": "/topics/notification", "notification": { "title": "新通知标题", "body": "这是通知的内容", "sound": "default" }, "data": { "custom_key": "自定义数据" // 可选,传递业务数据 } }
如果后端之前只发送了data字段,现在加上notification部分就能让系统自动弹窗了。
3. 完善iOS端的通知处理逻辑
结合你提供的代码,还有几个细节需要优化:
(1)调整主题订阅的位置
你现在把主题订阅代码放在didReceiveRemoteNotification里,这会导致每次收到推送才订阅,建议移到didFinishLaunchingWithOptions中,确保App启动时就完成订阅:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // ... 其他初始化代码 ... // 移到这里,确保启动时订阅主题 Messaging.messaging().subscribe(toTopic: "/topics/notification") { error in if let error = error { print("订阅主题失败: \(error.localizedDescription)") } else { print("成功订阅notification主题") } } return true }
(2)实现UNUserNotificationCenterDelegate的关键方法
对于iOS 10+,你已经设置了UNUserNotificationCenter.current().delegate = self,但还需要实现两个关键方法,确保前台和后台都能正确处理通知:
@available(iOS 10.0, *) extension AppDelegate: UNUserNotificationCenterDelegate { // App在前台时收到通知,允许弹窗展示 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { // 允许弹窗、声音和角标 completionHandler([.alert, .sound, .badge]) } // 用户点击通知时触发,处理自定义数据 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo // 这里可以处理通知携带的自定义数据 print("用户点击了通知,数据:\(userInfo)") completionHandler() } }
(3)如果必须使用Data消息的处理方式
如果你的业务场景只能发送Data消息,那需要在App收到消息时手动创建本地通知展示。比如在MessagingDelegate的方法中处理:
extension AppDelegate: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRemoteMessage remoteMessage: MessagingRemoteMessage) { print("收到Data消息: \(remoteMessage.appData)") // 手动创建本地通知 let content = UNMutableNotificationContent() content.title = remoteMessage.appData["title"] as? String ?? "通知" content.body = remoteMessage.appData["body"] as? String ?? "新消息" content.sound = .default let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("创建本地通知失败: \(error.localizedDescription)") } } } }
4. 额外检查点
- 确保你的iPhone没有开启专注模式或者通知静音,导致通知被隐藏。
- 检查App的通知权限是否正常:设置 -> 你的App -> 通知,确认“允许通知”和“横幅样式”已开启。
按照上面的步骤调整后,后端发送的通知应该就能正常弹窗展示了。
内容的提问来源于stack exchange,提问作者TheSwiftGuy77
相关产品推荐
相关产品推荐

