Les*_*nel 148 closures function optional swift3
鉴于:
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()
Run Code Online (Sandbox Code Playgroud)
有没有办法制作类型的completion参数(和action)Action?并保持@escaping?
更改类型会出现以下错误:
error: @escaping attribute only applies to function types
删除@escaping属性,代码编译并运行,但似乎不正确,因为completion闭包正在逃避函数的范围.
Dmi*_*rov 197
基本上,@ escaping仅对函数参数位置的闭包有效.noescape-by-default规则仅适用于函数参数位置的这些闭包,否则它们将被转义.聚合,例如具有关联值的枚举(例如可选),元组,结构等,如果它们具有闭包,则遵循不在函数参数位置的闭包的默认规则,即它们是转义的.
所以可选的函数参数默认是@escaping.
@noeascape默认只适用于函数参数.
Jan*_*ans 110
有一个SR-2552报告@escaping无法识别功能类型别名.这就是错误的原因@escaping attribute only applies to function 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()
Run Code Online (Sandbox Code Playgroud)
编辑1 ::
我实际上是在xcode 8 beta版本下,其中错误SR-2552尚未解决.修复那个bug,引入了一个仍然开放的新bug(你正面临的那个).见SR-2444.
解决方法@Michael Ilseman指出,临时解决方案是@escaping从可选函数类型中删除属性,使函数保持转义状态.
func doStuff(stuff: String, completion: Action?) {...}
Run Code Online (Sandbox Code Playgroud)
编辑2 ::
该SR-2444已经被关闭,说明明确,在参数位置关闭不逃逸,需要他们与被标记@escaping,使他们逃脱,但可选参数都隐含逃避,因为((Int)->())?是同义词Optional<(Int)->()>,可选的闭包逃跑.
小智 17
我遇到类似的问题,因为混合@escaping和非@escaping非常混乱,特别是如果你需要传递闭包.我最终得到默认参数(我觉得更有意义)
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)
}
Run Code Online (Sandbox Code Playgroud)
Igo*_*gor 17
我让它在Swift 3中工作,没有任何警告,只有这样:
func doStuff(stuff: String, completion: (()->())? ) {
print(stuff)
action = completion
completion?()
}
Run Code Online (Sandbox Code Playgroud)
在示例中要理解的重要一点是,如果更改Action为Action?闭包,则会转义。那么,让我们按照您的建议进行:
typealias Action = () -> ()
var action: Action? = { }
func doStuff(stuff: String, completion: Action?) {
print(stuff)
action = completion
completion?()
}
Run Code Online (Sandbox Code Playgroud)
好的,现在我们将调用doStuff:
class ViewController: UIViewController {
var prop = ""
override func viewDidLoad() {
super.viewDidLoad()
doStuff(stuff: "do stuff") {
print("swift 3!")
print(prop) // error: Reference to property 'prop' in closure
// requires explicit 'self.' to make capture semantics explicit
}
}
}
Run Code Online (Sandbox Code Playgroud)
嗯,这个要求只在逃避闭包时出现。所以闭包正在逃逸。这就是为什么你不将它标记为转义——它已经在转义了。
| 归档时间: |
|
| 查看次数: |
48795 次 |
| 最近记录: |