将闭包更新为 Swift 3 -@escape

我已经将我的代码更新到 Xcode 8.0 beta 6,但是我似乎被关于新的非转义闭包默认值的东西卡住了。在下面的代码中,Xcode 建议在下面代码的第一行的 completion:前面添加 @escaping,但是这仍然不能编译,而且在原地打转。*

(剪辑: 事实上,正如 Xcode 建议的那样,在 之后 completion:中应该添加@转义。警报可能仍会显示,但清理和编译会删除它。)* 应如何重新编写/修订这些代码,以便在更新后的 Swift 3中使用? 我看了一下新的手册,但是找不到合适的代码样本。

func doSomething(withParameter parameter: Int, completion: () -> ()) {
// Does something


callSomeOtherFunc(withCompletion: completion)
}


// Calling the method and execute closure
doSomething(withParameter: 2) {
// do things in closure
}

非常感谢你的帮助!

51662 次浏览

Swift 3: 闭包参数属性现在应用于参数 类型,而不是参数本身

在 Swift 3之前,闭包属性 @autoclosure@noescape曾经是闭包 参数的属性,但现在是参数 类型的属性; 请参阅以下已被接受的 Swift 演进提案:

您的具体问题涉及到参数类型属性 @escaping(同样的新规则也适用于该属性) ,正如已被接受的 Swift 进化建议中所描述的,该建议允许闭包参数在默认情况下不转义:

这些建议现在都在 Xcode 8的 beta 阶段实现(参见 Xcode 8 beta 6的发布说明; dev)。登入帐户)

Xcode 8 beta 6-Swift 编译器新增: Swift 语言

默认情况下,闭包参数是非转义的,而不是显式的 使用 @escaping表示一个 闭包参数可以转义。 @autoclosure(escaping)现在写成 注释 不推荐使用 @autoclosure(escaping)(SE-0103)

...

Xcode 8 beta-Swift 和 Apple LLVM 编译器中的新功能: Swift 语言

现在必须编写 @noescape@autoclosure属性 在参数类型之前,而不是在参数名称之前。[ SE-0049]

因此,使用非默认的 @escaping属性如下所示; 应用于闭包参数的 类型,而不是参数本身

func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
// ...
}

(包括我对一个问题的回答在下面的一个赞成的评论中,因为评论不是关于 SO 的持久性数据)

@ Cristi B lusomething: “逃跑有什么用? 从没见过这个关键词 在 Swift 3自动转换之前...”

例如,参见到 上述 SE-0103进化建议的链接(以及从 beta 6发行说明中引用的文本) : 以前,闭包参数在默认情况下是转义的(因此不需要存在显式的转义注释) ,但是现在在默认情况下是非转义的。因此,添加了 @escaping来显式地注释闭包参数可以转义(与其默认行为相反)。这也解释了为什么现在不推荐使用 @noescape(不需要注释默认行为)。

为了解释闭包参数转义的含义,我引用 语言参考-属性:

”将此属性应用于方法或函数声明中的参数类型,以指示参数的值可以存储为 这意味着该值可以比 电话的生命周期。”

@noescape

来自 xcode 8的 beta 6 @noescape是默认的。在此之前,@escaping是默认值。任何从早期版本更新到迅捷3.0的人都可能面临这个错误。

不能在变量中存储 @noescape闭包。因为如果可以在变量中存储闭包,则可以在代码中的任何位置执行闭包。但是 @noescape指出闭包参数不能转义函数体。

这将在 Xcode 8中给出编译器错误

class MyClass {


var myClosure: (() -> ())?


func doSomething(finishBlock: () -> ()) {
myClosure = finishBlock    // ‼️ Error: Assigning non-escaping parameter 'finishBlock' to an @escaping closure
}
}

这将编译 OK (显式编写 @escaping)

class MyClass {


var myClosure: (() -> ())?


func doSomething(finishBlock: @escaping () -> ()) {
myClosure = finishBlock
}
}

@noescape的好处:

  • 编译器可以优化代码以获得更好的性能
  • 编译器可以处理内存管理
  • 在闭包中没有必要使用弱引用自我


关于细节,请查看: 让非转义闭包成为默认闭包