澄清:
为了理解此案例,实现以下代码将会非常有用:
typealias completion = () -> ()
enum CompletionHandler {
case success
case failure
static var handler: completion {
get { return { } }
set { }
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler.handler = handlerParameter
}
乍一看,这段代码似乎是合法的,但实际上并不是!你会得到编译时错误的投诉:
error: assigning non-escaping
parameter 'handlerParameter' to an @escaping closure
let chObject = CompletionHandler.handler = handlerParameter
并附带一条注释:
note: parameter 'handlerParameter' is implicitly non-escaping func
doSomething(handlerParameter: completion) {
为什么呢?假设代码片段与 @escaping
没有关系...
实际上,从Swift 3发布开始,如果闭包默认声明在枚举、结构体或类中,它就会被“逃逸”。
参考文献,有相关问题汇报:
虽然它们可能与此案例没有百分之百相关性,但受让人的评论清楚地描述了该情况:
第一评论:
这里的实际问题是可选闭包现在隐式为 @escaping。
第二评论:
很遗憾,在Swift 3中是这样的。以下是Swift 3中逃逸的语义:
1)函数参数中的闭包默认为非逃逸
2)所有其他闭包都是逃逸的
因此,所有泛型类型参数中的闭包,如Array和 Optional,都是逃逸的。
显然,Optional
是枚举。
同样,如上所述,相同的行为也适用于类和结构体:
类情况:
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)
}
这两个代码片段将导致相同的输出(编译时错误)。
为了解决这个问题,您需要让函数签名变为:
func doSomething( handlerParameter: @escaping completion)
回到主要问题:
既然您预计必须让 completion:(()->())?
转义,那么如上所述会自动完成。