iOS端FCM推送通知图片不显示问题排查求助
带图片的FCM推送通知在iOS上无法显示的问题排查与解决
问题背景
我在iOS应用中使用Firebase Cloud Messaging (FCM)实现带图片的推送通知,已创建自定义NotificationServiceExtension处理图片下载与附件添加,但通知中的图片始终无法显示。
现有代码
NotificationService.swift
import UIKit import UserNotifications import FirebaseMessaging class NotificationService: UNNotificationServiceExtension { private var contentHandler: ((UNNotificationContent) -> Void)? private var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) defer { contentHandler(bestAttemptContent ?? request.content) } guard let attachment = request.attachment else { return } bestAttemptContent?.attachments = [attachment] } override func serviceExtensionTimeWillExpire() { if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } } extension UNNotificationRequest { var attachment: UNNotificationAttachment? { guard let attachmentURL = content.userInfo["image"] as? String, let imageData = try? Data(contentsOf: URL(string: attachmentURL)!) else { return nil } return try? UNNotificationAttachment(data: imageData, options: nil) } } extension UNNotificationAttachment { convenience init(data: Data, options: [NSObject: AnyObject]?) throws { let fileManager = FileManager.default let temporaryFolderName = ProcessInfo.processInfo.globallyUniqueString let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()) .appendingPathComponent(temporaryFolderName, isDirectory: true) try fileManager.createDirectory(at: temporaryFolderURL, withIntermediateDirectories: true, attributes: nil) let imageFileIdentifier = UUID().uuidString + ".jpg" let fileURL = temporaryFolderURL.appendingPathComponent(imageFileIdentifier) try data.write(to: fileURL) try self.init(identifier: imageFileIdentifier, url: fileURL, options: options) } }
FCM服务器端Payload
message = messaging.Message( data=convert_to_firebase_compatible(data), token=registration_id, android=messaging.AndroidConfig( priority='high', ttl=ttl ), notification=messaging.Notification( title=data.get('title', 'ABC'), body=data.get('message', ''), image=data.get('image_url', '') ), apns=messaging.APNSConfig( headers={ 'apns-priority': '10', }, payload=messaging.APNSPayload( aps=messaging.Aps( sound='default', mutable_content='1' ), ), fcm_options=messaging.APNSFCMOptions( image=data.get('image_url', '') ) ), )
问题现象
- iOS设备能正常收到通知,但图片无法显示
- 已确认userInfo中的图片URL有效且可直接访问
已执行的排查步骤
- 添加了
NotificationServiceExtension用于处理图片附件 - 验证Payload中的
image_url正确且可访问 - 确认Payload中
mutable_content已设置为"1"
疑问
- 配置
NotificationServiceExtension处理图片时是否遗漏了关键步骤? - 用于iOS通知图片的FCM Payload结构是否正确?
- 是否还需要额外配置APNs或FCM以支持通知图片?
解决方案
1. 修正Payload字段映射问题
你的UNNotificationRequest扩展中从userInfo["image"]获取图片URL,但当前Payload里iOS端的图片URL放在apns.fcm_options.image,FCM会将该字段映射到userInfo["gcm.image"]而非image。需要修改扩展的字段获取逻辑:
var attachment: UNNotificationAttachment? { guard let attachmentURL = content.userInfo["gcm.image"] as? String, let url = URL(string: attachmentURL) else { print("无效的图片URL") return nil } do { let imageData = try Data(contentsOf: url) return try UNNotificationAttachment(data: imageData, options: nil) } catch { print("加载图片或创建附件失败:\(error)") return nil } }
也可以直接在data参数中添加"image": data.get('image_url', ''),让图片URL直接出现在userInfo["image"]中。
2. 修复NotificationService的语法与错误处理
- 补上
bestAttemptContent赋值语句后的分号,避免潜在语法问题:
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
- 替换
try?为显式错误处理,方便排查问题,如上述代码中的打印逻辑。
3. 修正Payload参数类型
FCM的messaging.Aps接受布尔值而非字符串,将mutable_content改为布尔值:
aps=messaging.Aps( sound='default', mutable_content=True ),
4. 检查扩展配置
- 确认
NotificationServiceExtension的Target签名与主应用一致,且在扩展的Capabilities中开启了Push Notifications权限。 - 必须使用真机测试,模拟器无法正确处理通知附件。
内容的提问来源于stack exchange,提问作者WhisperingWinds
相关产品推荐
相关产品推荐

