如何在本地闭包中调用非转义闭包? [英] How to call non-escaping closure inside a local closure?
问题描述
我有一个看起来像这样的函数:
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屋!