更新closures到Swift 3 – @escaping

我已经更新了我的代码到Xcode 8.0 beta 6,但是我被卡住了似乎是关于新的非转义闭包默认。 在下面的代码中,Xcodebuild议在completion:添加@escaping completion:在下面的代码的第一行中,但是仍然不能编译并进行@escaping 。 *

编辑 :事实上,应该 completion: 之后添加@escaping,正如Xcode所build议的那样,警告仍然可以显示,但清理和编译将会删除它。)*这个代码应该如何重写/修改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 } 

任何帮助非常感谢!

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

在Swift 3之前,闭包属性@autoclosure@noescape曾经是闭包参数的属性,但是现在属于参数types ; 见下面接受的斯威夫特进化提议:

  • SE-0049:将@noescape和@autoclosure移动为types属性

你的具体问题涉及到参数types属性@escaping (为此应用相同的新规则),正如接受的Swift演进提议中所描述的那样,默认情况下让闭包参数不能转义:

  • SE-0103:使非转义closures成为默认值

这些提议现在都在Xcode 8的testing版阶段实现(请参阅Xcode 8 beta 6的发行说明 ;访问需要开发帐户login)

Xcode 8 beta 6中的新function – Swift编译器:Swift语言

Closure参数默认情况下是不转义的,而不是显式地用@noescape注释。 使用@escaping来指示一个闭包参数可能会转义。 @autoclosure(escaping)现在写成@autoclosure @escaping 。 注释@noescape@autoclosure(escaping)已被弃用。 (SE-0103)

Xcode 8 beta中的新function – Swift和Apple LLVM编译器:Swift语言

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

因此,您可以使用非默认的@escaping属性,如下所示: 应用于闭包参数的types ,而不是参数本身

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

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

@CristiBăluţă:“什么是转义行为?在swift3自动转换之前,从来没有看到这个关键字…”

请参阅上面SE-0103演进scheme的链接(以及beta6发行说明中的​​引用文本):以前,闭包参数默认是转义(因此不需要存在转义的显式注释),但现在默认情况下不是转义的。 因此,添加@escaping来显式注释一个闭包参数可能会转义(与其默认行为相反)。 这也解释了为什么@noescape现在被弃用(不需要注释默认行为)。

为了解释闭包参数是什么意思,我引用语言参考 – 属性 :

“将此属性应用于方法或函数声明中的参数types,以指示参数的值可以存储以供稍后执行,这意味着该值可以超过调用的生命周期。

@noescape

从Xcode 8 beta 6 @noescape是默认的。 在此之前, @escaping是默认的。 任何人从以前的版本更新到swift 3.0可能会面临这个错误。

您不能在variables中存储@noescape闭包。 因为如果你可以在一个variables中存储一个闭包,你可以在代码的任何地方执行闭包。 但@noescape指出,闭包参数不能逃避函数的主体。

这将在Xcode 8中发生编译器错误

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

这将编译好(明确写@escaping

 class MyClass { var myClosure: (() -> ())? func doSomething(finishBlock: @escaping () -> ()) { myClosure = finishBlock } } 

@noescape好处:

  • 编译器可以优化您的代码以获得更好的性能
  • 编译器可以照顾内存pipe理
  • 封闭中不需要使用自我的弱引用

有关详细信息, 请参阅: 使非转义closures成为默认closures