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
参数(和action
) Action?
并保持@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?() }