Swift 中重要特性——逃逸闭包@escaping

@escaping 是 Swift 中一个非常重要的特性,通常用于闭包(closure)的参数,尤其是在处理异步操作或回调时。它用于标记闭包参数"逃逸"出了函数的作用域,即闭包的生命周期超出了函数的执行范围。

为什么需要 @escaping

在 Swift 中,闭包默认是非逃逸(non-escaping)的,也就是说,闭包只能在函数调用过程中执行,并且不会保存到外部的变量或常量中。这样做的目的是提高性能,因为闭包不需要被保持,编译器可以进行优化。

然而,在处理异步操作时,比如网络请求或定时器,我们需要将闭包传递出去,让它在函数执行完毕后(甚至在函数退出后)继续执行。这时,闭包需要逃逸 出函数的作用域,这时就需要使用 @escaping 来显式标记这个闭包参数。

@escaping 的作用

@escaping 表示闭包会逃逸出函数的作用域,可以在函数返回后被执行。这通常用于处理异步回调或者其他延迟执行的场景。

关键点

  • 非逃逸闭包(non-escaping closure):闭包只能在函数内部执行,并且会在函数返回前执行完毕。默认情况下,函数的闭包参数是非逃逸的。
  • 逃逸闭包(escaping closure):闭包可以在函数返回之后仍然执行,通常用于异步回调。

例子:非逃逸闭包

如果没有使用 @escaping,闭包是非逃逸的,不能存储到函数外部。

swift 复制代码
func performTask(task: () -> Void) {
    task()  // 这里闭包被执行并且在函数内完成
}

例子:逃逸闭包

当闭包需要在函数执行完毕后仍然执行,通常会标记为 @escaping。最典型的例子是异步操作,例如网络请求或定时器。

swift 复制代码
func fetchData(completion: @escaping (Data?) -> Void) {
    DispatchQueue.global().async {
        // 模拟网络请求
        let data = Data()
        completion(data)  // 闭包会在函数返回后执行
    }
}

在上面的例子中,completion 闭包会逃逸出 fetchData 函数,因为它是在一个异步线程中执行的,函数返回后闭包才会被调用。

逃逸闭包与内存管理

由于逃逸闭包的生命周期可能超过函数的执行时间,它可能会导致内存管理问题。逃逸闭包会被持有到函数执行完成后,因此需要特别小心避免强引用循环(retain cycles)。

通常,为了避免强引用循环,我们会将闭包声明为 weakunowned,从而防止闭包持有对象的强引用。

使用 weakunowned 避免循环引用

swift 复制代码
func fetchData(completion: @escaping (Data?) -> Void) {
    DispatchQueue.global().async { [weak self] in
        // 使用 weak 或 unowned 防止循环引用
        guard let self = self else { return }
        let data = Data()
        completion(data)
    }
}

使用 @escaping 的实际场景

@escaping 主要用于异步操作或回调函数,它的作用是使闭包可以在函数执行完毕后,甚至在函数返回后继续执行。

  1. 网络请求回调:在网络请求成功或失败后执行回调操作。
  2. 定时器回调:在定时器触发时执行闭包操作。
  3. UI 更新回调:例如,在多线程中更新 UI,闭包可能需要在主线程执行。

总结

  • @escaping 标记闭包为逃逸闭包,即它可能在函数返回后被调用。
  • 逃逸闭包通常用于处理异步操作、回调等情况。
  • 逃逸闭包的生命周期可能会超过函数的作用域,因此需要注意内存管理,避免出现强引用循环。
相关推荐
东风破_5 小时前
danci 项目(三):从 JSON 数据到 AI Coding,真实项目里的数据清洗、Prompt 和工程规范
前端·后端·node.js
东风破_5 小时前
danci 项目(一):从需求到架构,一个单词学习系统为什么会这样设计
前端·后端·node.js
蒲公英eric6 小时前
从客户端到服务端:DVWA DOM 型 XSS 模块完整漏洞分析教程
前端·web安全·ai·xss·dvwa·ai安全
单线程_016 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
顶点多余6 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
Setsuna_F_Seiei6 小时前
前端转型 Agent 开发 03 之 Agent Tools - 给 Agent 装上手脚
前端·agent·ai编程
jay神7 小时前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
kyriewen9 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
风骏时光牛马9 小时前
大模型落地实践中的技术选型思路与方案对比
前端
sakiko_10 小时前
Swift学习笔记42-SwiftUI的属性包装器(讲解+面试)
笔记·学习·ios·swiftui·swift