如何在函数内存储non-escaping closure?报错原因解析
关于Swift中非逃逸闭包存储报错的解释
尝试在函数内部存储非逃逸闭包时,会触发如下编译错误:
error: Converting non-escaping parameter 'completionHandler' to generic parameter 'Element' may allow it to escape
触发报错的示例代码如下:
func someFunctionWithNonEscapingClosure(completionHandler: () -> Void) { var completionHandlers: [() -> Void] = [] completionHandlers.append(completionHandler) }
错误原因解析
根据Swift官方文档对非逃逸闭包的定义:非逃逸闭包会在函数体执行完毕后立即离开作用域并从内存中销毁,其生命周期完全被限制在函数内部。但将它存入函数内的局部数组仍会报错,核心原因在于Swift编译器的安全检测机制:
- 虽然数组是函数内部的局部变量,但编译器无法保证后续代码不会将该数组传出函数(比如作为返回值、传递给其他逃逸闭包等)。一旦数组被传出,里面的闭包就会脱离原函数的作用域,违反非逃逸闭包的生命周期约束。
- 数组的
append方法是泛型实现,编译器会检测到:将非逃逸参数completionHandler转换为数组的泛型元素类型Element,存在让闭包逃逸的风险,因此直接抛出错误拦截。
解决方法
如果确实需要存储该闭包,有两种可行方向:
- 将闭包参数标记为逃逸闭包,添加
@escaping关键字,明确允许闭包脱离函数作用域:func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) { var completionHandlers: [() -> Void] = [] completionHandlers.append(completionHandler) } - 若必须保持非逃逸特性,则只能在函数执行期间直接调用闭包,不能将其存入任何可能延长生命周期的容器(如数组、字典等)。
内容的提问来源于stack exchange,提问作者Dev karan
相关产品推荐
相关产品推荐

