Swift 3可选的转义闭包参数

鉴于:

typealias Action = () -> () var action: Action = { } func doStuff(stuff: String, completion: @escaping Action) { print(stuff) action = completion completion() } func doStuffAgain() { print("again") action() } doStuff(stuff: "do stuff") { print("swift 3!") } doStuffAgain() 

有什么办法可以使Action?types的completion参数(和actionAction? 并保持@escaping

更改types会导致以下错误:

error: @escaping attribute only applies to function types

除去@escaping属性,代码编译并运行,但是由于completion闭包正在逃避函数的作用域,所以似乎并不正确。

有一个SR-2552报告说, @escaping不能识别函数types别名。 这就是为什么错误@escaping attribute only applies to function types 。 您可以通过扩展函数签名中的函数types来解决此问题:

 typealias Action = () -> () var action: Action? = { } func doStuff(stuff: String, completion: (@escaping ()->())?) { print(stuff) action = completion completion?() } func doStuffAgain() { print("again") action?() } doStuff(stuff: "do stuff") { print("swift 3!") } doStuffAgain() 

编辑 ::

我实际上是在一个Xcode 8testing版的问题SR-2552尚未解决。 修复这个bug,引入一个新的(你正在面对的)仍然是开放的。 见SR-2444 。

解决方法Michael Ilseman指出,临时解决scheme是从可选的函数types中删除@escaping属性,将该函数保留为转义。

 func doStuff(stuff: String, completion: Action?) {...} 

来自: swift-users邮件列表

基本上,@escaping仅在函数参数位置的闭包中有效。 noescape-by-default规则仅适用于函数参数位置的这些闭包,否则它们是逃避的。 具有关联值的枚举(例如可选),元组,结构等(如果它们具有闭包)的集合遵循不在函数参数位置的闭包的默认规则,即它们正在逃逸。

所以可选的函数参数默认是@escaping。
@noeascape默认只适用于函数参数。

我碰到类似的问题,因为混合@escaping和非@escaping是非常混乱,特别是如果你需要通过closures周围。 我最终的默认参数(我认为更有意义)

 func doStuff(stuff: String = "do stuff", completion: @escaping (_ some: String) -> Void = { _ in }) { completion(stuff) } doStuff(stuff: "bla") { stuff in print(stuff) } doStuff() { stuff in print(stuff) } 

我在Swift 3中工作,没有任何警告,只有这样:

 func doStuff(stuff: String, completion: (()->())? ) { print(stuff) action = completion completion?() }