逃逸闭包:不需要在函数结束前被调用,可以等到特定时机时才被调用
非逃逸闭包:不需要其它特殊时机,只能在函数作用域内函数执行结束前被调用
非逃逸闭包
给函数test传递一个闭包参数callback,此时闭包callback调用只能在函数作执行结束前被当做函数内的任务依次被执行,这种情况下的闭包就是非逃逸闭包。 ```swift class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.test {
print("非逃逸")
}
}
func test(callback:()->()) {
print("1")
callback()
print("2")
}
}
非逃逸闭包的生命周期:<br />1、闭包作为参数传给函数;<br />2、函数中运行改闭包;<br />3、退出函数。
- 逃逸闭包
给当前类声明一个闭包变量escapingCallback,将test函数内的闭包参数赋值给这个变量,此时这个闭包就可以在函数执行结束后或其他时候被调用。
```swift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.test {
print("逃逸")
}
}
func test(callback:@escaping()->()) {
print("1")
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
callback()
}
print("2")
}
}
逃逸闭包的生命周期:
1、闭包作为参数传递给函数;
2、退出函数;
3、闭包被调用,闭包生命周期结束
即逃逸闭包的生命周期长于函数,函数退出的时候,逃逸闭包的引用仍被其他对象持有,不会在函数结束时释放。
为什么要分逃逸闭包和非逃逸闭包 为了管理内存,闭包会强引用它捕获的所有对象,比如你在闭包中访问了当前控制器的属性、函数,编译器会要求你在闭包中显示 self 的引用,这样闭包会持有当前对象,容易导致循环引用。
非逃逸闭包不会产生循环引用,它会在函数作用域内释放,编译器可以保证在函数结束时闭包会释放它捕获的所有对象;使用非逃逸闭包的另一个好处是编译器可以应用更多强有力的性能优化,例如,当明确了一个闭包的生命周期的话,就可以省去一些保留(retain)和释放(release)的调用;此外非逃逸闭包它的上下文的内存可以保存在栈上而不是堆上。