如何在本地闭包内调用非转义闭包?

时间:2016-10-16 17:01:00

标签: swift closures swift3

我有一个看起来像这样的函数:

func test(closure: () -> ()) {
    let localClosure = { closure() }

    localClosure()
}

这只是一个例子,并没有完全反映我遇到的问题,显然我可以直接调用closure

应该很清楚,在上面的代码中,closure无法逃脱。但是,我收到错误:

  

关闭使用非转义参数'closure'可能允许它转义

现在,如果localClosure以某种方式逃脱,我会理解这个错误,但它并没有逃脱。我甚至尝试将localClosure注释为@noescape(即使该属性在Swift 3中已弃用),并根据我得到的警告:

  

@noescape是默认,已弃用

如果localClosure默认情况下是非转义的,那么为什么另一个非转义闭包不能进入呢?或者这是编译器的错误/限制?

1 个答案:

答案 0 :(得分:5)

非参数闭包是@escaping,默认为

  

"如果localClosure默认情况下是非逃避,那么为什么......"

根据以下评论中的讨论(感谢@Hamish),我们可以在Swift 3.0中声明以下有关非参数闭包的事实:

  • 默认情况下,它们与人们可能认为的相反,@escaping。由于@noescape在Swift 3中已弃用(请参阅例如Xcode 8 release notesSwift evolution proposal SE-0103),这意味着如果不使用已弃用的方法,则不能使非参数闭包非转义。
  • the following evolution thread中所述,非参数闭包缺少@noescape属性是一个缺失的特征(有点回归,因为这不是Swift 2.2中的限制),但是不一定要在将来实施(如果我要理解苹果开发人员乔丹·罗斯在链接进化线程中的答案)。
  • 但是,我们仍然可以(仍然)将已弃用的@noescape属性应用于非参数闭包以使其无法转义,但会显着提示不正确的警告(如下所示,强调我的),现在已被@Hamish报告为bug,请参阅bug report SR-2969

      

    " @noescape 是默认,已弃用"

总而言之,localClosure@escaping,这自然意味着不能允许它包装closure的非转义闭包参数test(...)

<子> [†]通过非参数闭包,我指的是函数的 not 参数的所有闭包,即 not 作为参数提供给函数的闭包。

作为旁注,您可能已经知道了问题:如果我们希望按照您的示例处理/换行,我们可以自然地将closure标记为@escaping

func test(closure: @escaping () -> ()) -> () -> () {
    let escapingLocalClosure = { closure() }
    return escapingLocalClosure
}