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

Flutter EventChannel在iOS端无值返回问题排查求助

问题解决:Flutter EventChannel无法接收iOS蓝牙状态更新

根因分析

你的代码里,CBManagerStateController仅在Flutter端首次监听时(onListen方法)通过eventSink发送了一次初始状态值。当蓝牙状态变化时,BluetoothManager虽然更新了全局变量,但没有触发eventSink发送新值,导致Flutter端收不到后续状态更新。同时,全局变量的方式也容易引发状态不同步问题,不符合iOS开发的最佳实践。

解决方案

核心是让BluetoothManager在状态变化时直接通知CBManagerStateController调用eventSink发送新状态到Flutter端,具体修改如下:

1. 重构BluetoothManager,添加状态回调

移除全局变量,新增闭包属性传递状态更新:

class BluetoothManager: NSObject, CBCentralManagerDelegate {
    private var centralManager: CBCentralManager
    var onStateChanged: ((Int) -> Void)? // 状态变化回调闭包

    override init() {
        self.centralManager = CBCentralManager(delegate: nil, queue: nil)
        super.init()
        centralManager.delegate = self
        // 初始化时主动发送一次当前状态
        onStateChanged?(centralManager.state.rawValue)
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        let stateValue = central.state.rawValue
        print("IOS: cbManagerState updated state is:", stateValue)
        onStateChanged?(stateValue) // 触发回调,推送新状态
    }
}

2. 修改CBManagerStateController,保存eventSink并监听状态

保留eventSink引用,同时订阅BluetoothManager的状态变化:

class CBManagerStateController: NSObject, FlutterStreamHandler {
    private var eventSink: FlutterEventSink?
    private let bluetoothManager: BluetoothManager

    // 初始化时传入BluetoothManager
    init(bluetoothManager: BluetoothManager) {
        self.bluetoothManager = bluetoothManager
        super.init()
        print("IOS: CBManagerStateController is instantiated")
        // 绑定蓝牙状态变化监听
        bluetoothManager.onStateChanged = { [weak self] state in
            self?.eventSink?(state)
        }
    }

    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        // 发送当前初始状态
        let currentState = bluetoothManager.centralManager.state.rawValue
        print("IOS: centralManager state in the controller is:", currentState)
        events(currentState)
        return nil
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        eventSink = nil
        bluetoothManager.onStateChanged = nil // 取消回调,避免内存泄漏
        return nil
    }
}

3. 调整AppDelegate初始化逻辑,关联管理器与控制器

确保CBManagerStateController与BluetoothManager正确绑定:

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            let controller = window?.rootViewController as! FlutterViewController
            
            let bluetoothManager = BluetoothManager() // 创建蓝牙管理器实例
            
            let cbManagerStateChannel = FlutterEventChannel(name: "cbmanager_state_channel", binaryMessenger: controller.binaryMessenger)
            // 传入bluetoothManager初始化控制器
            let cbManagerStateController = CBManagerStateController(bluetoothManager: bluetoothManager)
            
            cbManagerStateChannel.setStreamHandler(cbManagerStateController)
            
            GeneratedPluginRegistrant.register(with: self)
            return super.application(application, didFinishLaunchingWithOptions: launchOptions)
        }
}

Flutter端代码验证

你的Flutter端逻辑无需修改,只需确认:

  • EventChannel名称与iOS端完全一致(此处为cbmanager_state_channel)
  • Riverpod的cBManagerStateProvider正确返回流,UI通过ref.watch正常监听状态

修改完成后,iOS端蓝牙状态变化时,BluetoothManager会触发回调,CBManagerStateController会立即通过eventSink推送新状态到Flutter端,UI即可实时更新蓝牙状态。

内容的提问来源于stack exchange,提问作者Gustavo Ramos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:23:20