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

Flutter iOS端如何在AppDelegate中调用eventSink处理UserIntent并传数据到Dart

可行实现方案

方案1:通过NotificationCenter中转数据(推荐,耦合度最低)

无需修改原有访问权限,通过系统通知实现跨组件数据传递:

  1. 在插件类中注册通知观察者,收到通知后调用eventSink回传数据
public class SwiftMyPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
    private var eventSink: FlutterEventSink?

    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        // 注册UserIntent接收通知
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleIntentNotification(_:)),
            name: NSNotification.Name("UserIntentReceived"),
            object: nil
        )
        return nil
    }

    public func onCancel(withArguments arguments: Any?) -> FlutterError? {
        // 移除观察者,清空eventSink避免内存泄漏
        NotificationCenter.default.removeObserver(self)
        eventSink = nil
        return nil
    }

    @objc private func handleIntentNotification(_ notification: Notification) {
        guard let userInfo = notification.userInfo,
              let intentData = userInfo["intentData"] as? String, // 可根据实际需求修改数据类型
              let sink = eventSink else { return }
        // 必须在主线程调用eventSink
        DispatchQueue.main.async {
            sink(intentData)
        }
    }

    // 原有其他插件逻辑保持不变
    public static func register(with registrar: FlutterPluginRegistrar) {
        let methodChannel = FlutterMethodChannel(name: "your_method_channel", binaryMessenger: registrar.messenger())
        let eventChannel = FlutterEventChannel(name: "your_event_channel", binaryMessenger: registrar.messenger())
        let instance = SwiftMyPlugin()
        eventChannel.setStreamHandler(instance)
        registrar.addMethodCallDelegate(instance, channel: methodChannel)
    }
}
  1. 在AppDelegate的UserIntent回调中发送通知
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // 解析userActivity中的需要传递给Dart侧的数据
    let intentData = userActivity.userInfo?["your_data_key"] as? String ?? ""
    // 发送通知携带数据
    NotificationCenter.default.post(
        name: NSNotification.Name("UserIntentReceived"),
        object: nil,
        userInfo: ["intentData": intentData]
    )
    return super.application(application, continue: userActivity, restorationHandler: restorationHandler)
}

方案2:静态存储插件实例直接调用

通过静态共享实例直接访问插件内的eventSink:

  1. 在插件类中新增静态共享实例,注册时使用该实例
public class SwiftMyPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
    // 全局唯一静态实例
    public static let shared = SwiftMyPlugin()
    var eventSink: FlutterEventSink?

    public static func register(with registrar: FlutterPluginRegistrar) {
        let methodChannel = FlutterMethodChannel(name: "your_method_channel", binaryMessenger: registrar.messenger())
        let eventChannel = FlutterEventChannel(name: "your_event_channel", binaryMessenger: registrar.messenger())
        // 直接使用静态实例,不要重新初始化
        let instance = SwiftMyPlugin.shared
        eventChannel.setStreamHandler(instance)
        registrar.addMethodCallDelegate(instance, channel: methodChannel)
    }

    // 实现onListen和onCancel存储eventSink
    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        return nil
    }

    public func onCancel(withArguments arguments: Any?) -> FlutterError? {
        eventSink = nil
        return nil
    }
}
  1. 在AppDelegate中直接调用静态实例的eventSink
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    let intentData = userActivity.userInfo?["your_data_key"] as? String ?? ""
    if let sink = SwiftMyPlugin.shared.eventSink {
        DispatchQueue.main.async {
            sink(intentData)
        }
    } else {
        // 可选:Dart侧尚未监听时暂存数据,后续监听后再回传
        UserDefaults.standard.set(intentData, forKey: "cachedIntentData")
    }
    return super.application(application, continue: userActivity, restorationHandler: restorationHandler)
}

补充说明

你之前尝试1失败的核心原因大概率是AppDelegate重写了application(continue:userActivity:)方法后未调用super实现,导致Flutter无法将事件分发给注册的插件代理,在该方法末尾加上return super.application(...)即可触发插件内的代理回调。

注意事项

  • eventSink必须在主线程调用,若数据处理逻辑在子线程,需切换到主线程再执行sink操作
  • 若Dart侧尚未监听EventChannel,eventSink会为nil,此时可将intent数据暂存在本地存储/全局变量中,等Dart侧发起监听时再将缓存数据回传

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:39:03