Skip to content

18.5_逃逸闭包escaping

逃逸闭包:让你的闭包“逃离”函数 🚀

在 Swift 中,闭包是非常强大的工具,可以让你编写更灵活、更简洁的代码。但是,有时候闭包的生命周期会超出其被定义的函数范围,这时就需要用到 @escaping 标记。让我们一起深入了解逃逸闭包吧!

什么是逃逸闭包? 🤔

简单来说,当一个闭包作为参数传递给函数,并且在函数返回之后才被调用,那么这个闭包就称为逃逸闭包。这意味着闭包的生命周期超过了函数本身。你可以想象成闭包“逃离”了函数的作用域。

  • 非逃逸闭包 (默认): 函数执行结束前调用。
  • 逃逸闭包: 函数执行结束后调用。

为什么要使用 @escaping? 🧐

Swift 需要知道闭包是否会逃逸,以便进行内存管理。当闭包逃逸时,它需要被存储在堆上,而不是栈上。使用 @escaping 告诉编译器,这个闭包会逃逸,编译器会采取相应的措施来确保内存安全。如果不使用 @escaping,编译器可能会报错,或者导致程序崩溃。

如何使用 @escaping? ✍️

使用 @escaping 非常简单。只需要在闭包类型的参数前面加上 @escaping 关键字即可。例如:

swift
func doSomething(completionHandler: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        completionHandler() // 2秒后调用闭包
    }
}

在这个例子中,completionHandler 是一个逃逸闭包,因为它在 doSomething 函数返回后 2 秒才被调用。

逃逸闭包的常见场景 🗺️

逃逸闭包在异步编程中非常常见。以下是一些常见的场景:

  1. 网络请求: 当你发起一个网络请求时,通常会使用一个闭包来处理请求完成后的结果。这个闭包通常是逃逸闭包,因为它在请求完成时才被调用,而请求完成的时间可能在函数返回之后。
  2. 定时器: 当你使用定时器时,通常会使用一个闭包来执行定时任务。这个闭包也是逃逸闭包,因为它在定时器触发时才被调用,而定时器触发的时间可能在函数返回之后。
  3. 存储属性: 逃逸闭包可以赋值给存储属性,延长闭包的生命周期。

逃逸闭包的注意事项 ⚠️

  • 循环引用: 使用逃逸闭包时,需要注意避免循环引用。如果闭包捕获了 self,并且 self 也持有闭包,那么就会形成循环引用,导致内存泄漏。可以使用 [weak self][unowned self] 来解决循环引用问题。
  • 内存管理: 逃逸闭包需要被存储在堆上,因此会增加内存管理的负担。需要确保及时释放不再使用的逃逸闭包,以避免内存泄漏。

总而言之,@escaping 标记是 Swift 中处理逃逸闭包的关键。理解并正确使用 @escaping 可以帮助你编写更安全、更高效的代码。希望你能掌握逃逸闭包,并在你的 Swift 项目中灵活运用!🎉

本站使用 VitePress 制作