鉴于:

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?型的completion参数(和action)同时保持@escaping

更改类型会导致以下错误:

@转义属性仅适用于函数类型

删除@escaping属性后,代码将编译并运行,但似乎不正确,因为completion闭包正在脱离函数的作用域.

推荐答案

有一个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()

EDIT 1::

事实上,我在一个xcode 8测试版下,bug SR-2552还没有解决.修复了这个漏洞,引入了一个新的(你正在面对的)仍然开放的漏洞.见SR-2444.

临时解决方案@Michael Ilseman是从可选函数类型that keep the function as escaping中删除@escaping属性.

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

EDIT 2::

SR-2444已被关闭,明确说明参数中的闭包位置are not正在转义,需要用@escaping标记以使其转义,但可选参数are隐式转义,因为((Int)->())?Optional<(Int)->()>的同义词,可选闭包正在转义.

Swift相关问答推荐

如何使用Swift宏向 struct 体及其init函数添加新成员?

减go 用SWIFT struct 填充的NSCountedSet

在visionOS RealityView中使用.GenerateText时,未显示Reality Composer Promaterial 纹理

如何在SwiftUI中更改NSTextView中的 Select colored颜色 ?

在 Swift 5.7 中使用协议作为类型时什么时候需要写 `any`

使用异步收集发布者值

并发执行代码中捕获的 var 的变异

Swift - 给定一个像 30 的 Int 如何将范围数乘以 7?

创建 ViewModel 时 iOS 模拟器上的黑屏

`let case(value)` 和 `case(let value)` 之间的区别 (Swift)

是否可以使任何协议符合 Codable?

不使用 ViewController 时如何显示推送通知的alert 对话框

Vapor 4,如何按外键过滤?

Swift 读写图片占用大量内存

swift 如何从 Int 转换?到字符串

'NSLog' 不可用:可变参数函数在 swift 中不可用

为 UIActivityViewController Swift 设置不同的活动项

如何使用 swift 在 tableview 中填充两个不同数组的两个部分?

Xcode-beta 8. 无法创建核心数据

在Swift中的String对象中的特定字符之后删除所有字符的更优雅的方法是什么