如何在本地闭包中调用非转义闭包? [英] How to call non-escaping closure inside a local closure?

查看:137
本文介绍了如何在本地闭包中调用非转义闭包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a function which looks something like this:

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

    localClosure()
}

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

很明显,在上面的代码中,closure无法转义.但是,我得到了错误:

It should be clear that in the above code, closure cannot escape. However, I get the error:

关闭使用非转义参数'closure'可能使其逃脱

Closure use of non-escaping parameter 'closure' may allow it to escape

现在,如果localClosure以某种方式转义,我会理解此错误,但是它不会逃脱.我什至尝试将localClosure注释为@noescape(即使该属性在Swift 3中已弃用),并且根据警告我得到了:

Now, if localClosure was escaping in some way, I'd understand this error, but it doesn't escape. I even tried annotating localClosure as @noescape (even though that attribute is deprecated in Swift 3), and according to the warning I got:

@noescape是默认,已弃用

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

If localClosure is, by default, non-escaping, then why can't another non-escaping closure go inside it? Or is this a bug/limitation of the compiler?

推荐答案

默认情况下,非参数闭包为@escaping

如果默认情况下localClosure是非转义的,那为什么..."

"If localClosure is, by default, non-escaping, then why ..."

基于下面评论中的讨论(感谢@Hamish),我们可以陈述有关Swift 3.0中非参数闭包的以下事实:

Based on the discussion in the comments below (thanks @Hamish), we can state the following facts regarding non-parameter closures in Swift 3.0:

  • 默认情况下,与人们可能会相信的相反,它们是@escaping.由于@noescape在Swift 3中已弃用(请参见例如 Xcode 8发行说明迅速发展提案SE-0103 ),这意味着如果不使用不推荐使用的方法,就不能使非参数闭包成为非转义.
  • 以下演化线程所述,,缺少非参数闭包的@noescape属性是一项缺少的功能(有点回归,因为这不是Swift 2.2中的限制),但不一定在将来实现(如果我要了解Apple开发人员Jordan Rose在链接的演化线程中的答案.
  • 但是,我们可以(仍然)将已弃用的@noescape属性应用于非参数闭包,以使其不转义,但随后会特别提示您输入错误的警告(如下所示,强调我的意思), @Hamish现在已将其报告为错误,请参见错误报告SR-2969 .

  • They are, contrary to what one might believe, @escaping, by default. As @noescape is deprecated in Swift 3 (see e.g. Xcode 8 release notes or Swift evolution proposal SE-0103), this means that non-parameter closures cannot be made non-escaping without making use of deprecated methods.
  • As described in the following evolution thread, the lack of @noescape attribute for non-parameter closures is a missing feature (somewhat of a regression as this was not a limitation in Swift 2.2), but one that is not necessarily to be implemented in the future (if I'm to understand the answer by Apple dev. Jordan Rose in the linked evolution thread).
  • We may however (still) apply the deprecated @noescape attribute to a non-parameter closure to make it non-escaping, but will then notably be prompted with an incorrect warning (as below, emphasis mine), which has now been reported as a bug by @Hamish, see bug report SR-2969.

"@noescape 为默认,已弃用"

"@noescape is default and is deprecated"

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

To summarize, localClosure is @escaping, which naturally means it cannot be allowed to wrap the non-escaping closure parameter closure of test(...).

[†]对于非参数闭包,我指的是函数的所有 not 参数的闭包,即,作为参数提供给函数的 not 的闭包.

[†] By non-parameter closures, I refer to all closures that are not parameters to a function, i.e., closures that are not supplied to a function as an argument.

作为一个旁注,您可能已经知道了您的问题:如果我们希望像您的示例中那样处理/包装closure,我们自然可以将closure标记为@escaping.

As a side-note, which you possibly already knows given your question: we may naturally mark closure as @escaping if we'd wish to process/wrap it as in your example.

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

这篇关于如何在本地闭包中调用非转义闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆