You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase Push Notification后台无法正常工作问题求助

解决FCM后台推送无法触发下载和本地通知的问题

我来帮你搞定这个问题,这在iOS开发里是个常见的坑,主要和iOS的推送机制、FCM的消息类型有关,咱们一步步排查:

1. 先搞懂FCM的两种消息类型

iOS后台推送的核心规则要记牢:

  • 纯通知消息(只有notification字段):后台时系统直接帮你弹通知,根本不会走你的自定义代码逻辑,所以下载和本地通知自然触发不了。
  • 数据消息/混合消息:只有带data字段的消息,后台才会把控制权交还给你的APP,让你处理下载和本地通知。
    • 混合消息(同时有notification和data):后台时系统会先弹通知,用户点击通知后才会触发你的代码;
    • 纯数据消息:后台时会直接触发你的推送处理方法(前提是开了后台权限)。

2. 必须开启后台推送权限

首先在Info.plist里配置后台模式:

  • 添加UIBackgroundModes数组,把remote-notification加进去。这是APP能在后台接收推送并干活的基础。

3. 正确实现推送回调方法

看你的代码只贴了权限请求的部分,你还需要补充这些关键方法:

针对iOS 10+的UNUserNotificationCenter(推荐用这个)

// 前台收到推送时触发
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    // 调用你的下载和本地通知逻辑
    handlePushContent(notification.request.content.userInfo)
    // 允许前台展示通知
    completionHandler([.alert, .badge, .sound])
}

// 后台/未启动时,用户点击通知触发
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    handlePushContent(response.notification.request.content.userInfo)
    completionHandler()
}

处理纯数据消息的后台回调

如果发的是纯数据消息,后台会直接走这个方法:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    handlePushContent(userInfo)
    // 告诉系统你处理完了,用.newData表示有新内容
    completionHandler(.newData)
}

别忘了在didFinishLaunchingWithOptions里补全FCM的配置:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // 请求通知权限
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound]) { granted, error in
        if granted {
            application.registerForRemoteNotifications()
        }
    }
    // 设置FCM和通知中心代理
    Messaging.messaging().delegate = self
    UNUserNotificationCenter.current().delegate = self
    return true
}

// 实现FCM代理获取令牌
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    print("FCM令牌:\(fcmToken ?? "")")
    // 把令牌发给你的服务器用来推送
}

4. 后台下载要延长运行时间

iOS后台给APP的默认运行时间很短(大概30秒),如果下载耗时久,系统会直接杀进程。你需要用后台任务来续命:

func handlePushContent(_ userInfo: [AnyHashable: Any]) {
    var backgroundTask: UIBackgroundTaskIdentifier = .invalid
    // 开始后台任务
    backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "PushDownload") {
        // 超时了,结束任务
        UIApplication.shared.endBackgroundTask(backgroundTask)
        backgroundTask = .invalid
    }
    
    // 模拟下载操作
    downloadExtraContent(from: userInfo["content_url"] as? String) { [weak self] in
        // 下载完成触发本地通知
        self?.sendLocalNotification(title: userInfo["title"] as? String ?? "新内容")
        // 结束后台任务
        UIApplication.shared.endBackgroundTask(backgroundTask)
        backgroundTask = .invalid
    }
}

5. 测试要注意正确姿势

  • 别用Xcode调试后台推送!Xcode会让APP保持活跃状态,不算真正的后台。你得把APP退到后台,或者直接断开Xcode在真机上运行。
  • 确保服务器端发的消息格式正确,比如纯数据消息的示例:
{
  "to": "你的设备FCM令牌",
  "data": {
    "content_url": "https://example.com/your-content",
    "title": "新内容已更新"
  }
}

内容的提问来源于stack exchange,提问作者Rezwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:43:45