更新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