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

iOS 10下Firebase通知点击弹窗:APP被杀状态无响应如何解决?

嘿,这个问题我之前帮不少开发者解决过——APP被杀状态下didReceiveRemoteNotification确实不会触发,因为iOS在这种场景下会直接启动APP,不会走这个旧的回调。咱们得换iOS 10之后推出的UserNotifications框架来处理,这才是官方推荐的正确姿势,具体解决方案如下:

解决方案:改用UserNotifications框架实现全状态通知点击弹窗

核心思路是利用UNUserNotificationCenter的代理方法,它能覆盖APP前台、后台、被杀三种状态下的通知点击事件。

1. 初始化配置UserNotifications

在AppDelegate的didFinishLaunchingWithOptions里完成基础配置,同时处理被杀状态下启动APP的通知数据暂存:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 确保Firebase初始化已存在
    FirebaseApp.configure()
    
    // 配置UserNotifications代理与权限
    UNUserNotificationCenter.current().delegate = self
    let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in
        guard granted else { return }
        DispatchQueue.main.async {
            application.registerForRemoteNotifications()
        }
    }
    
    // 处理被杀状态下点击通知启动APP的情况:暂存通知数据
    if let notificationData = launchOptions?[.remoteNotification] as? [AnyHashable: Any] {
        UserDefaults.standard.set(notificationData, forKey: "PendingNotification")
    }
    
    return true
}

2. 实现UNUserNotificationCenterDelegate代理方法

让AppDelegate遵循协议,实现通知接收与点击的回调:

extension AppDelegate: UNUserNotificationCenterDelegate {
    // APP前台收到通知时的回调(可选,如需前台也弹窗可启用)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // 前台展示系统通知弹窗
        completionHandler([.alert, .sound])
        // 同时弹出自定义弹窗
        showNotificationAlert()
    }
    
    // 点击通知时的回调(覆盖所有状态:后台、被杀)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // 弹出自定义弹窗
        showNotificationAlert()
        completionHandler()
    }
}

3. 处理被杀状态下的弹窗时机

当APP从被杀状态启动时,根ViewController可能还未加载完成,直接弹窗会失败。可以在根VC的viewDidAppear里检查暂存的通知数据:

class RootViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // 检查是否有暂存的通知数据
        if UserDefaults.standard.object(forKey: "PendingNotification") != nil {
            showNotificationAlert()
            // 弹窗后清除暂存数据
            UserDefaults.standard.removeObject(forKey: "PendingNotification")
        }
    }
}

4. 封装通用弹窗方法

把弹窗逻辑抽成通用方法,方便各处调用:

func showNotificationAlert() {
    DispatchQueue.main.async {
        guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else { return }
        let alertController = UIAlertController(title: "Alert", message: "you have a new notification", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "Yes", style: .default) { _ in
            // 这里添加点击"Yes"后的业务逻辑
        }
        alertController.addAction(okAction)
        rootVC.present(alertController, animated: true, completion: nil)
    }
}

关键注意事项

  • 推送Payload必须包含aps字段:Firebase推送时,payload里要带aps节点(哪怕是空的alert),否则系统不会识别为通知消息,点击后无法触发回调。示例Payload:
    {
      "aps": { "alert": {} },
      "customData": "your_info"
    }
    
  • 权限校验:必须确保用户授权了通知的.alert权限,否则弹窗无法展示。
  • 场景适配:如果你的APP使用了SceneDelegate,需要把UNUserNotificationCenter的代理设置在SceneDelegate中,并在scene(_:willConnectTo:options:)里处理启动参数中的通知数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:07:22