为了理解这种情况,实现以下代码将很有用:
typealias completion = () -> ()
enum CompletionHandler {
case success
case failure
static var handler: completion {
get { return { } }
set { }
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler.handler = handlerParameter
}
乍一看,此代码似乎合法,但事实并非如此!您会收到 编译时错误抱怨:
: assigning non-escaping parameter ‘handlerParameter’ to an @escaping closure
let chObject = CompletionHandler.handler = handlerParameter
with a note that:
: parameter ‘handlerParameter’ is implicitly non-escaping func doSomething(handlerParameter: completion) {
这是为什么?假设是代码段已无关的@escaping…
实际上,由于Swift 3已发布,如果默认在enum,struct或class中声明了闭包,则闭包将被“转义” 。
As a reference, there are bugs reported related to this issue:
尽管它们可能与本案并非100%相关,但受让人的评论 清楚地描述了该案:
The actual issue here is that
不幸的是,Swift 3就是这种情况。这是 Swift 3中转义的语义:
2)所有其他关闭都在逃逸
因此,所有通用类型参数闭包(例如Array和Optional) 都在转义。
ObvIoUsly,Optional
is enum.
同样-如上所述,相同的行为也适用于 类和结构:
typealias completion = () -> ()
class CompletionHandler {
var handler: () -> ()
init(handler: () -> ()) {
self.handler = handler
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
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)
既然你期待,你必须让completion:(()->())?被逃脱,会自动完成-as上面描述。