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

Flutter调用Swift异步库无法await结果,如何替代sleep实现等待?

问题

在Flutter应用中调用Swift异步库时,无法正常awaitSwift异步操作的结果。当前代码中,subscription的sink闭包不会执行,但添加sleep(5)后能正常运行,希望找到无需sleep的解决方案。

现有代码

Swift代码

...
    nfcChannel.setMethodCallHandler({
      (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
      switch call.method {
      case "doCGM":
        self.readCGM(result: result)
      default:
        result(FlutterMethodNotImplemented)
      }
    })
...

private func readCGM(result: @escaping FlutterResult) {
      let device = UIDevice.current
      
      var nfcManager = LibreTools.makeNFCManager(unlockCode: 0, password: Data([1, 2, 3, 4]))

      //perform a request
      let subscription = nfcManager.perform(.readHistory)
          .sink { reading in
             print("Reading done!!!")
             result(reading)
          }

      //sleep(5);
      //print("I am done")
  }

Flutter代码

Future<bool> _handleIOS() async {
    // Sensor type
    logger.info('Trying to read data from iOS');
    dynamic data = await platform.invokeMethod('doCGM');
    logger.info('Random data: $data');
    return true;
  }
解决方案

问题核心是**subscription作为局部变量,在readCGM方法执行完毕后会被立即释放**,导致异步流还未执行就被销毁,所以sink闭包无法触发。添加sleep只是通过延迟方法结束时间,让subscription暂时存活到异步操作完成,不是合理方案。

可以通过以下两种方式保证订阅在异步操作完成前不被销毁:

方式1:将订阅保存为类成员变量

在Swift类中声明成员变量存储订阅,确保其生命周期覆盖异步操作:

// 在类中添加成员变量
private var nfcSubscription: AnyCancellable?

...

private func readCGM(result: @escaping FlutterResult) {
      let device = UIDevice.current
      
      var nfcManager = LibreTools.makeNFCManager(unlockCode: 0, password: Data([1, 2, 3, 4]))

      // 保存订阅到成员变量
      nfcSubscription = nfcManager.perform(.readHistory)
          .sink { reading in
             print("Reading done!!!")
             result(reading)
             // 操作完成后置空,释放资源
             nfcSubscription = nil
          }
  }

方式2:用Set集合管理订阅

在类中声明Set<AnyCancellable>,通过store(in:)方法保存订阅:

// 在类中添加成员变量
private var cancellables = Set<AnyCancellable>()

...

private func readCGM(result: @escaping FlutterResult) {
      let device = UIDevice.current
      
      var nfcManager = LibreTools.makeNFCManager(unlockCode: 0, password: Data([1, 2, 3, 4]))

      nfcManager.perform(.readHistory)
          .sink { reading in
             print("Reading done!!!")
             result(reading)
          }
          .store(in: &cancellables) // 将订阅存入集合,避免被释放
  }

修改后,订阅会在异步操作完成前保持存活,无需sleep就能正常触发sink闭包,并通过result将数据返回给Flutter端,Flutter的await也能正确获取到异步结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:20:53