Swift 里的闭包(Closure)对应 ObjC 里的代码块(Block)。
众所周知,在闭包里引用外部变量其引用数会递增,但如果是在闭包所在的方法内部立即就执行的,引用数递增是没有必要的。
为了让编译器能优化这种情况,Swift 为此增加了两个注解:@escaping
和 @noescape
。
@escaping
:逃逸性闭包,表示告诉编译器这个闭包是稍后才执行的,里面的变量需要被捕获。
@noescape
:非逃逸闭包,闭包现在就会被执行,告诉编译器不要捕获里面的变量。
Swift 里对不加注明的闭包,都会当作非逃逸闭包(@noescape
)处理。
但是对于可选类型的闭包,比如:((Int)->())?
,默认是逃逸闭包(@escaping
)。
默认情况下 Swfit 会把 ObjC 的代码块(Block)都当成逃逸闭包处理,为了能和 Swift 更好的兼容,ObjC 提供了一个宏:NS_NOESCAPE
NS_NOESCAPE
对应 Swift 里的 @noescape
,需要在非逃逸的代码块的声明和实现里都标明上这个宏:
- (void)foo:(NS_NOESCAPE void (^)(void))block;
- (void)foo:(NS_NOESCAPE void (^)(void))block {
// ...
}