主要理解点 : @escaping关键字修饰的闭包类型改怎么用?怎么理解?
- 逃逸闭包
当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸. 当你定义接受闭包作为参数的函数时,你可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个函数的.
简单粗暴的理解 : 逃逸闭包就是把这个传入的block可以保存在外部.等待某一时刻你可以再次调用这个block.这一个时刻是在函数返回之后.
Demo测试
//一种能使闭包“逃逸”出函数的方法是,将这个闭包保存在一个函数外部定义的变量中。
//这里是一个闭包数组
typealias completionHandlerBlock = () -> Void
var completionHandlers: [completionHandlerBlock] = []
class SomeClass {
var x = 10
func doSomething() {
someFunctionWith_Escaping_Closure { self.x = 200 } //将一个闭包标记为 @escaping 意味着你必须在闭包中显式地引用 self。
someFunctionWith_Non_Escaping_Closure { x = 200 } //不带self
}
//逃逸闭包
func someFunctionWith_Escaping_Closure(completionHandler: @escaping completionHandlerBlock) {
//函数接受一个闭包作为参数,该闭包被添加到一个函数外定义的数组中。如果你不将这个参数标记为 @escaping,就会得到一个编译错误。
completionHandlers.append(completionHandler)
}
//非逃逸闭包
func someFunctionWith_Non_Escaping_Closure(closure: () -> Void) {
//该闭包是一个非逃逸闭包,这意味着它可以隐式引用 self。同时无法保存在外部
completionHandlers.append(closure) //报错 : Passing non-escaping parameter 'closure' to function expecting an @escaping closure
closure()
}
}
方法调用 :
override func viewDidLoad() {
super.viewDidLoad()
let instance = SomeClass()
instance.doSomething()
print(instance.x) // 打印出 "200"
completionHandlers.first?()
print(instance.x) // 打印出 "100"
}