当前位置: 首页 > news >正文

Swift的逃逸闭包

@escaping (SCCMDResult) -> Void 逃逸闭包的作用是

@escaping (SCCMDResult) -> Void 中的 @escaping(逃逸闭包) 在 Swift 中非常重要,它表示这个闭包可能会在函数返回后被调用

基本概念

非逃逸闭包(默认)

swift

func executeCommand(completion: (SCCMDResult) -> Void) {// 闭包在函数结束前被调用completion(.success)// 函数返回
}

逃逸闭包

swift

func executeCommand(completion: @escaping (SCCMDResult) -> Void) {// 将闭包存储起来,稍后调用self.completionHandler = completion// 函数返回,但闭包可能还没有被调用!
}

在你的代码中的应用

在你之前的 ViewModel 代码中,可以看到逃逸闭包的使用:

swift

// 这些方法都使用了 @escaping 闭包
SCLibertyCMDSendManager().setEasychatInfoTest(data: data) { _, _ in// 这个闭包是逃逸的,因为蓝牙操作是异步的
}SCLibertyCMDSendManager().getEasychatInfoTest { [weak self] result, data in// 这个闭包会在网络/蓝牙请求完成后被调用// 此时 init() 函数可能已经返回很久了
}SCLibertyCMDSendManager().getEasychatStatusTest { result, data in// 同样,这个闭包会逃逸
}

为什么需要 @escaping

1. 异步操作

蓝牙命令、网络请求、定时器等都需要逃逸闭包:

swift

class BluetoothManager {private var completionHandlers: [((SCCMDResult) -> Void)] = []func sendCommand(completion: @escaping (SCCMDResult) -> Void) {// 存储闭包,等待蓝牙响应completionHandlers.append(completion)// 发送蓝牙命令(异步)sendBluetoothData { response in// 在未来的某个时间点回调let handler = self.completionHandlers.removeFirst()handler(response)}}
}

2. 存储闭包

在你的防抖代码中:

swift

private let emergencyDebounce = SCDebounce(interval: 0.5)func setTimeCMD() {let data = Data([...])emergencyDebounce.execute {// 这个闭包被 SCDebounce 存储起来,在 0.5 秒后执行SCLibertyCMDSendManager().setEasychatInfoTest(data: data) { _, _ in// 这也是一个逃逸闭包}}// 函数立即返回,但闭包还在等待执行
}

3. DispatchQueue 异步执行

swift

func delayedExecution(completion: @escaping (SCCMDResult) -> Void) {DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {// 1秒后执行,此时函数早已返回completion(.success)}
}

内存管理注意事项

由于逃逸闭包会延长生命周期,需要特别注意循环引用

❌ 错误写法(循环引用)

swift

class MyViewModel {var result: SCCMDResult?func fetchData() {SCLibertyCMDSendManager().getEasychatInfoTest { result, data in// 闭包强引用了 selfself.result = result  // 导致循环引用!}}
}

✅ 正确写法(使用 weak self)

swift

class MyViewModel {var result: SCCMDResult?func fetchData() {SCLibertyCMDSendManager().getEasychatInfoTest { [weak self] result, data in// 使用弱引用self?.result = result  // 不会导致循环引用}}
}

实际场景分析

在你的代码中:

swift

private func getInfoCMD() {SCLibertyCMDSendManager().getEasychatInfoTest { [weak self] result, data in// 这个 @escaping 闭包在:// 1. 蓝牙命令发送后// 2. 设备响应数据时(可能是几毫秒或几秒后)// 3. 被调用,此时 getInfoCMD() 函数早已结束guard let self = self else { return }if result == .success {// 处理数据...}self.isLoading = false  // 更新UI状态}
}

总结

@escaping 闭包的作用:

  1. 允许异步回调 - 在函数返回后执行

  2. 支持闭包存储 - 可以保存在属性或数组中

  3. 启用延迟执行 - 通过 DispatchQueue 或定时器

  4. 需要内存管理 - 必须注意 [weak self] 避免循环引用

在你的蓝牙命令场景中,@escaping 是必需的,因为蓝牙通信是异步的,响应会在未来的某个时间点到达,而不是在函数执行期间。

http://www.dtcms.com/a/596669.html

相关文章:

  • ESP32基础-GPIO_LED进阶
  • AT指令连接onenet平台(mqtt协议)
  • 二分搜索中 `right = mid` 而非 `right = mid + 1` 的解释
  • 走进Linux的世界:进程优先级
  • 蛙蛙写作网站中国建设银行网站-个人客
  • jetson开机之前自启脚本sudo ifconfig 如何不需要输入密码
  • 环评登记表在哪个网站做php网站开发试题
  • K8S RD: Kubernetes核心技术之管理、高可用与配置详解
  • Rust:Trait 抽象接口 特征约束
  • 【Windows】tauri+rust运行打包工具链安装
  • 网站被人抄袭怎么办哪家做网站的公司
  • 在 Linux 上实现 Spring Boot 程序的自动启动与守护运行
  • 得物TiDB升级实践
  • uni-app微信小程序相机组件二次拍照白屏问题的排查与解决
  • 邯郸大名网站建设网站服务器类型查询
  • 远程在线诊疗|在线诊疗|基于java和小程序的在线诊疗系统小程序设计与实现(源码+数据库+文档)
  • Linux进程间通信(IPC)常用方法精要
  • 展望无人机的未来发展,技术趋势和应用前景
  • 黄页 网站模板什么是展示型网站
  • gov域名网站有哪些如何建一个免费试用网站
  • Vue中 class 和 style 属性的区别对比
  • 视频融合平台EasyCVR:构建智慧化城市/乡镇污水处理厂综合安防与运营监管方案
  • 【ZeroRange WebRTC】KVS WebRTC C SDK 崩溃分析报告
  • 库卡机器人编程语言 | 深入了解库卡机器人的编程方法与应用
  • 移动+协作+视觉=?复合型机器人重新定义智能产线
  • 【macOS 版】Android studio jdk 1.8 gradle 一键打包成 release 包的脚本
  • 网站关键词优化原理亳州做企业网站
  • 数据库知识整理——SQL数据定义
  • AAAI 2026|港科大等提出ReconVLA:利用视觉重构引导,刷新机器人操作精度!(含代码)
  • Java 进阶:IO 流与 Lambda 表达式深度解析