[英]Swift optional escaping closure
Compiler error Closure use of non-escaping parameter 'completion' may allow it to escape
, Which make sense because it will be called after the function return. 编译器错误Closure use of non-escaping parameter 'completion' may allow it to escape
,这是有道理的,因为它将在函数返回后调用。
func sync(completion:(()->())) {
self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
completion()
}
}
But if I make closure optional then no compiler error, Why is that? 但是,如果我将闭包设为可选,则不会出现编译器错误,那是为什么呢? closure can still be called after the function returns. 函数返回后仍可以调用闭包。
func sync(completion:(()->())?) {
self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
completion?()
}
}
Wrapping a closure in an Optional automatically marks it escaping. 将闭包包装在Optional中会自动将其转义。 It's technically already "escaped" by being embedded into an enum (the Optional). 从技术上讲,它已经被嵌入枚举(“可选”)“转义”了。
For understanding the case, implementing the following code would be useful: 为了理解这种情况,实现以下代码将很有用:
typealias completion = () -> ()
enum CompletionHandler {
case success
case failure
static var handler: completion {
get { return { } }
set { }
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler.handler = handlerParameter
}
At the first look, this code seems to be legal, but it's not! 乍一看,此代码似乎合法,但事实并非如此! you would get compile-time error complaining: 您将收到编译时错误抱怨:
error : assigning non-escaping parameter 'handlerParameter' to an @escaping closure 错误 :将非转义参数'handlerParameter'分配给@转义闭包
let chObject = CompletionHandler.handler = handlerParameter 让chObject = CompletionHandler.handler = handlerParameter
with a note that: 注意:
note : parameter 'handlerParameter' is implicitly non-escaping func doSomething(handlerParameter: completion) { 注意 :参数'handlerParameter'是隐式非转义函数doSomething(handlerParameter:完成){
Why is that? 这是为什么? the assumption is that the code snippet has nothing to do with the @escaping
... 假设代码片段与@escaping
没有@escaping
...
Actually, since Swift 3 has been released, the closure will be "escaped" if it's declared in enum , struct or class by default. 实际上,由于Swift 3已发布,因此默认情况下,如果在enum , struct或class中声明了闭包,则闭包将被“转义”。
As a reference, there are bugs reported related to this issue: 作为参考,报告了与该问题有关的错误:
Although they might not 100% related to this case, the assignee comments are clearly describe the case: 尽管它们可能与本案并非100%相关,但受让人的评论清楚地描述了该案:
First comment : 第一条评论 :
The actual issue here is that optional closures are implicitly @escaping right now. 这里的实际问题是, 可选的闭包现在隐式@转义。
Second comment : 第二条评论 :
That is unfortunately the case for Swift 3. Here are the semantics for escaping in Swift 3: 不幸的是,Swift 3就是这种情况。这是Swift 3中转义的语义:
1) Closures in function parameter position are non-escaping by default 1)默认情况下,函数参数位置的闭包不转义
2) All other closures are escaping 2) 所有其他关闭都在逃逸
Thus, all generic type argument closures, such as Array and Optional , are escaping. 因此,所有通用类型参数闭包(例如Array和Optional )都在转义。
Obviously, Optional
is enum. 显然, Optional
是枚举。
Also -as mentioned above-, the same behavior would be applicable for the classes and structs: 同样-如上所述,相同的行为也适用于类和结构:
Class Case: 类案例:
typealias completion = () -> ()
class CompletionHandler {
var handler: () -> ()
init(handler: () -> ()) {
self.handler = handler
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
Struct Case: 结构案例:
typealias completion = () -> ()
struct CompletionHandler {
var handler: completion
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
The two above code snippets would leads to the same output (compile-time error). 上面的两个代码段将导致相同的输出(编译时错误)。
For fixing the case, you would need to let the function signature to be : 为了解决这个问题,您需要让函数签名为 :
func doSomething( handlerParameter: @escaping completion)
Since you are expecting that you have to let the completion:(()->())?
因为您期望您必须让completion:(()->())?
to be escaped, that would automatically done -as described above-. 为了逃脱,这将自动完成-如上所述-。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.