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

Flutter+OneSignal:iOS后台推送通知更新UI问题求助

问题解答

1. NotificationServiceExtension 能否向 AppDelegate 传递数据?

可以,但无法直接通过内存共享——Extension 和主 App 运行在独立进程,属于不同沙盒容器。实现跨进程数据传递的常用方式是通过 App Groups 共享存储:

  1. 登录苹果开发者后台,给主应用和 NotificationServiceExtension 配置同一个 App Group(例如 group.com.your.app.notification)
  2. 在两端代码中使用带 App Group 标识的 UserDefaults:
    // NotificationServiceExtension 中写入通知数据
    let sharedDefaults = UserDefaults(suiteName: "group.com.your.app.notification")
    sharedDefaults?.set(notificationContent.userInfo, forKey: "latest_notification")
    sharedDefaults?.synchronize()
    
    // AppDelegate 中在后台唤醒时主动读取
    override func applicationDidBecomeActive(_ application: UIApplication) {
        super.applicationDidBecomeActive(application)
        let sharedDefaults = UserDefaults(suiteName: "group.com.your.app.notification")
        if let notification = sharedDefaults?.value(forKey: "latest_notification") {
            flutterChannel.invokeMethod("getNotification", arguments: notification)
            // 读取后清空,避免重复处理
            sharedDefaults?.removeObject(forKey: "latest_notification")
        }
    }
    

除了 UserDefaults,也可以用 Keychain 实现共享(同样需要配置 App Group),适合存储敏感数据。

2. 能否直接将 NotificationServiceExtension 中的数据传递至 Flutter 端?

不行。NotificationServiceExtension 进程中没有 Flutter 引擎实例,无法获取 binaryMessenger,因此无法直接通过 MethodChannel 调用 Flutter 方法。必须先将数据传递到主 App 进程,再由主 App 转发给 Flutter。

3. 其他捕获通知并传递至 Flutter 端的方案

方案一:利用 OneSignal 原生回调(最推荐)

你的 didReceiveRemoteNotification 方法未触发,大概率是因为 OneSignal SDK 已经接管了该生命周期方法。可以通过 OneSignal 提供的回调来捕获通知:

// AppDelegate 中添加 OneSignal 通知接收监听
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // 先让 OneSignal 处理通知逻辑
    OneSignal.didReceiveRemoteNotification(userInfo, fetchCompletionHandler: completionHandler)
    // 提取通知数据传递给 Flutter
    if let alert = userInfo["aps"]?["alert"] as? [String: Any], let title = alert["title"], let body = alert["body"] {
        flutterChannel.invokeMethod("getNotification", arguments: ["title": title, "body": body])
    }
}

同时在 Flutter 端,也可以直接监听 OneSignal 的通知回调:

OneSignal.Notifications.addForegroundWillDisplayListener((event) {
  // 前台收到通知时更新列表
  updateNotificationList(event.notification);
});

OneSignal.Notifications.addClickListener((event) {
  // 点击通知时更新列表
  updateNotificationList(event.notification);
});

方案二:后台唤醒时读取共享数据

当 NotificationServiceExtension 将通知数据写入 App Group 共享存储后,主 App 在后台被唤醒时(例如收到推送通知后系统触发唤醒),主动读取共享数据并传递给 Flutter,实现列表更新。

方案三:使用 APNS 静默推送

如果只需要更新列表而无需显示通知,可以发送静默推送(推送 payload 包含 content-available: 1,不含 alert 字段),此时主 App 的 didReceiveRemoteNotification 会被触发,直接处理数据并传递给 Flutter。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:25:05