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 秒才被调用。
逃逸闭包的常见场景 🗺️
逃逸闭包在异步编程中非常常见。以下是一些常见的场景:
- 网络请求: 当你发起一个网络请求时,通常会使用一个闭包来处理请求完成后的结果。这个闭包通常是逃逸闭包,因为它在请求完成时才被调用,而请求完成的时间可能在函数返回之后。
- 定时器: 当你使用定时器时,通常会使用一个闭包来执行定时任务。这个闭包也是逃逸闭包,因为它在定时器触发时才被调用,而定时器触发的时间可能在函数返回之后。
- 存储属性: 逃逸闭包可以赋值给存储属性,延长闭包的生命周期。
逃逸闭包的注意事项 ⚠️
- 循环引用: 使用逃逸闭包时,需要注意避免循环引用。如果闭包捕获了
self,并且self也持有闭包,那么就会形成循环引用,导致内存泄漏。可以使用[weak self]或[unowned self]来解决循环引用问题。 - 内存管理: 逃逸闭包需要被存储在堆上,因此会增加内存管理的负担。需要确保及时释放不再使用的逃逸闭包,以避免内存泄漏。
总而言之,@escaping 标记是 Swift 中处理逃逸闭包的关键。理解并正确使用 @escaping 可以帮助你编写更安全、更高效的代码。希望你能掌握逃逸闭包,并在你的 Swift 项目中灵活运用!🎉