在半年前的一次面试中...
面试官:网络请求的 block 怎么写的?
我:
func request(completion: (() -> Void)?)
面试官:不需要加
@escaping
吗?我:不需要
面试官:为什么?
我:这个闭包是可选的
面试官:这是一个逃逸闭包,逃逸闭包要加
@escaping
,和闭包是不是可选有什么关系?我:不知道...
内心OS:我也不知道为什么啊...可我这么写没报错啊...
先说结论,以下两个方法都不会报错,接下来就来说说为什么第二个方法不会报错。
func request(completion: @escaping () -> Void) { }
func request(completion: (() -> Void)?) { }
首先我们要知道可选类型的本质是什么?可选类型的本质是一个枚举,声明如下。
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
}
所以第二个方法实际上是这样子的。
func request(completion: Optional<() -> Void>) { }
因为可选闭包本质是一个枚举,completion
参数传递的是一个枚举,所以不需要加上 @escaping
。