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
相关产品推荐
相关产品推荐

