Flutter自定义iOS插件添加SDK代理后无法触发回调问题
问题分析与解决方案
你的核心问题是Flutter iOS插件中CustomSDK的代理回调未触发,虽然scan()能执行且SDK内部有扫描日志,但CustomSDKDelegate的方法完全没响应,而原生Swift应用正常。大概率是代理的生命周期管理或方法签名兼容性出了问题,以下是针对性的排查和修复方案:
可能的问题点与修复步骤
1. 插件实例被释放导致代理失效
很多第三方SDK的代理是weak引用,如果SwiftIosPlugin的实例被提前释放,代理自然会失效。Flutter的registrar虽然会持有methodCallDelegate的引用,但某些场景下仍可能出现实例被回收的情况。
修复方案:把插件改成单例模式,确保实例始终被强持有
public class SwiftIosPlugin: NSObject, FlutterPlugin { // 定义单例,保证实例不被释放 static let shared = SwiftIosPlugin() let sdkInstance = CustomSDK.shared let channel: FlutterMethodChannel // 私有初始化方法,避免外部创建实例 private init() { let flutterVC = UIApplication.shared.delegate?.window??.rootViewController as! FlutterViewController self.channel = FlutterMethodChannel(name: "ios_plugin_channel", binaryMessenger: flutterVC) super.init() // 单例初始化时添加代理,确保代理对象存活 sdkInstance.addDelegate(self) } public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "ios_plugin_channel", binaryMessenger: registrar.messenger()) // 注册单例作为代理 registrar.addMethodCallDelegate(shared, channel: channel) registrar.addApplicationDelegate(shared) } // 原handle方法保留,调整connect方法的参数处理 public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "startScan": do { try sdkInstance.scan() result(nil) } catch { result(FlutterError(code: "400", message: "\(error)", details: nil)) } case "connect": // 从Flutter传参中提取设备ID,适配SDK的connect方法 guard let deviceId = call.arguments as? String else { result(FlutterError(code: "INVALID_ARG", message: "缺少设备ID参数", details: nil)) return } sdkInstance.connect(deviceId) result(nil) default: result(FlutterMethodNotImplemented) } } }
2. 代理方法签名不兼容(Objective-C SDK场景)
如果CustomSDK是Objective-C编写的,Swift实现代理时需要确保方法被标记为@objc,否则Objective-C端无法识别到代理方法。
修复方案:给代理扩展和方法添加@objc标记
// 给整个代理扩展添加@objc,确保Objective-C能识别 @objc extension SwiftIosPlugin: CustomSDKDelegate { @objc public func onScanDevice(didScan id: String) { // 切换到主线程调用Flutter Channel,避免线程问题 DispatchQueue.main.async { self.channel.invokeMethod("onScanDevice", arguments: ["deviceId": id]) } } @objc public func onPairedDevice(didPair id: String) { DispatchQueue.main.async { self.channel.invokeMethod("onPairedDevice", arguments: ["deviceId": id]) } } }
3. 回调线程不匹配
Flutter的Method Channel要求必须在主线程调用invokeMethod,如果SDK的代理回调在后台线程执行,直接调用Channel会导致无响应或崩溃。
修复方案:所有代理回调中强制切换到主线程处理
如上面代码所示,用DispatchQueue.main.async包裹Channel调用逻辑。
额外排查点
- 确认
CustomSDK的addDelegate方法是否支持多代理,如果是单代理模式,检查是否有其他地方提前添加了代理导致覆盖。 - 验证
CustomSDK.shared是否为真正的单例,避免插件中获取的实例和原生应用中不一致。
内容的提问来源于stack exchange,提问作者Jorge Rincón Arias
相关产品推荐
相关产品推荐

