Flutter iOS端如何在AppDelegate中调用eventSink处理UserIntent并传数据到Dart
可行实现方案
方案1:通过NotificationCenter中转数据(推荐,耦合度最低)
无需修改原有访问权限,通过系统通知实现跨组件数据传递:
- 在插件类中注册通知观察者,收到通知后调用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) } }
- 在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:
- 在插件类中新增静态共享实例,注册时使用该实例
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 } }
- 在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
相关产品推荐
相关产品推荐

