闭包只有在函数中做参数的时候才会区分逃逸闭包和非逃逸闭包
在Swift 3 后,传递闭包到函数中的时候,系统会默认为非逃逸闭包类型 (Nonescaping Closures)@noescape,有非逃逸闭包类型必然就有逃逸闭包(Escaping Closures),逃逸闭包在闭包前要添加@escaping关键字
非逃逸闭包的生命周期:1.把闭包作为参数传给函数;2.函数中调用闭包;3.退出函数,闭包生命周期结束
即非逃逸闭包的生命周期与函数相同
逃逸闭包的生命周期:1.闭包作为参数传递给函数;2.退出函数; 3.闭包被调用,闭包生命周期结束
即逃逸闭包的生命周期长于函数,函数退出的时候,逃逸闭包的引用仍被其他对象持有,不会在函数结束时释放
例子:
非逃逸闭包:
import UIKit
class HttpTool: NSObject {
1 func loadData(callBack:((String)->())){
2 callBack("非逃逸闭包")
3 }
}
ViewController类:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var tools:HttpTool = HttpTool()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
tools.loadData { (jsonData:String) in
print(jsonData);
}
}
}
代码执行顺序1,2,3
当传递闭包参数给函数loadData时,要注意ViewController中的属性tools,虽然闭包会捕获self,但是由于默认闭包参数是非逃逸型,这里可以省略 self, 反正编译器已经知道这里不会有循环引用的潜在风险。
逃逸闭包:
import UIKit
class HttpTool: NSObject {
func loadData(callBack:@escaping((String)->())){
1 DispatchQueue.global().async {
DispatchQueue.main.async {
2 callBack("这是逃逸闭包")
}
}
3 }
}
ViewController类:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var tools:HttpTool = HttpTool()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
tools.loadData { (jsonData:String) in
print(jsonData);
}
}
}
代码执行顺序1,3,2
当传递闭包参数给函数loadData时,要注意ViewController中的属性tools,这里闭包函数的生命周期在函数结束后结束,tools前面省略的self 就有必要做特殊处理,防止造成死循环。
逃逸闭包在闭包前要添加@escaping关键字,这里的闭包的生命周期不可预知
以后有用到逃逸闭包的例子,会及时更新,也欢迎看见的小伙伴帮忙补充