众所周知,函数和闭包是Swift语言中的一等公民,在程序中可以把它作为值存储起来,也作为参数传递给函数。
在Swift 3.x 中,传递闭包到函数中的时候,系统会默认为非逃逸闭包类型 (Nonescaping Closures),有非逃逸闭包类型必然就有逃逸闭包(Escaping Closures), 这里简单聊聊两者的关系。
非逃逸闭包
非逃逸闭包的生命周期比较简单:
把闭包作为参数传递给函数。
函数中运行该闭包。
退出函数。
非逃逸闭包
显而易见是非逃逸闭包被限制在函数内,当函数退出的时候,该闭包引用计数不会增加,也就是说其引用计数在进入函数和退出函数时保持不变。
逃逸闭包
逃逸闭包恰恰与非逃逸闭包相反,其生命周期长于相关函数,当函数退出的时候,逃逸闭包的引用仍然被其他对象持有,不会在相关函数结束后释放。
逃逸闭包
如上图所示,当函数结束的时候,闭包依然会在外面的世界里逍遥快活,对于内存管理来说这可不是好现象。
注意
要谨慎使用@escaping(逃逸闭包),除非明确知道要使用它做什么。
下面是使用逃逸闭包的2个场景:
异步调用: 如果需要调度队列中异步调用闭包, 这个队列会持有闭包的引用,至于什么时候调用闭包,或闭包什么时候运行结束都是不可预知的。
存储: 需要存储闭包作为属性,全局变量或其他类型做稍后使用。
欢迎补充更多使用场景。
网友评论