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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:50:25