将闭包更新为 Swift 3 - @escaping
Updating closures to Swift 3 - @escaping
我已将我的代码更新为 Xcode 8.0 beta 6,但我被新的非转义闭包默认值所困扰。在下面的代码中,Xcode 建议在下面代码的第一行 completion:
前面添加 @escaping
,但仍然无法通过循环。 *
(EDIT: 其实@escaping应该在after completion:
中加上,如Xcode建议。警报可能仍会显示,但清理和编译会删除它。)* 应该如何重写/修复此代码以在更新的 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:闭包参数属性现在应用于参数 type,而不是参数本身
在Swift3之前,闭包属性@autoclosure
和@noescape
曾经是闭包参数的属性,但现在是参数 type 的属性;请参阅以下接受的 Swift 进化建议:
您的具体问题与参数类型属性 @escaping
(适用相同的新规则)有关,如已接受的 Swift 演化提案中所述,默认情况下让闭包参数不转义:
这些提议现在都在 Xcode 8 的测试阶段实施(参见 release notes for Xcode 8 beta 6;访问需要开发帐户登录)
New in Xcode 8 beta 6 - Swift Compiler: Swift Language
Closure parameters are non-escaping by default, rather than explicitly
being annotated with @noescape
. Use @escaping
to indicate that a
closure parameter may escape. @autoclosure(escaping)
is now written as
@autoclosure @escaping
. The annotations @noescape
and
@autoclosure(escaping)
are deprecated. (SE-0103)
...
New in Xcode 8 beta – Swift and Apple LLVM Compilers: Swift Language
The @noescape
and @autoclosure
attributes must now be written
before the parameter type instead of before the parameter name. [SE-0049]
因此,您使用非默认 @escaping
属性如下;应用于闭包参数的类型,而不是参数本身
func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
// ...
}
(包括我在下面的评论中对一个问题的回答,因为评论不是关于 SO 的持久数据)
@Cristi Băluță: "What does escaping do? Never seen this keywords
before swift3 auto-conversion ... "
参见例如link 到 SE-0103 evolution proposal above(以及 beta 6 发行说明中引用的文本):以前,闭包参数默认转义(因此不需要存在用于转义的显式注释) ,但现在默认情况下是非转义的。因此,添加 @escaping
以明确注释闭包参数可能会转义(与其默认行为相反)。这也解释了为什么 @noescape
现在已被弃用(无需注释默认行为)。
为了解释闭包参数转义的含义,我引用 Language Reference - attributes:
"Apply this attribute to a parameter’s type in a method or function declaration to indicate that the parameter’s value can be stored for
later execution. This means that the value is allowed to outlive the
lifetime of the call."
@noescape
来自 xcode 8 beta 6 @noescape
是默认值。在此之前,@escaping
是默认值。从以前的版本更新到 swift 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
的好处:
- 编译器可以优化您的代码以获得更好的性能
- 编译器可以负责内存管理
- 不需要在闭包中使用self的弱引用
有关详细信息,请查看:Make non-escaping closures the default
我已将我的代码更新为 Xcode 8.0 beta 6,但我被新的非转义闭包默认值所困扰。在下面的代码中,Xcode 建议在下面代码的第一行 completion:
前面添加 @escaping
,但仍然无法通过循环。 *
(EDIT: 其实@escaping应该在after completion:
中加上,如Xcode建议。警报可能仍会显示,但清理和编译会删除它。)* 应该如何重写/修复此代码以在更新的 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:闭包参数属性现在应用于参数 type,而不是参数本身
在Swift3之前,闭包属性@autoclosure
和@noescape
曾经是闭包参数的属性,但现在是参数 type 的属性;请参阅以下接受的 Swift 进化建议:
您的具体问题与参数类型属性 @escaping
(适用相同的新规则)有关,如已接受的 Swift 演化提案中所述,默认情况下让闭包参数不转义:
这些提议现在都在 Xcode 8 的测试阶段实施(参见 release notes for Xcode 8 beta 6;访问需要开发帐户登录)
New in Xcode 8 beta 6 - Swift Compiler: Swift Language
Closure parameters are non-escaping by default, rather than explicitly being annotated with
@noescape
. Use@escaping
to indicate that a closure parameter may escape.@autoclosure(escaping)
is now written as@autoclosure @escaping
. The annotations@noescape
and@autoclosure(escaping)
are deprecated. (SE-0103)...
New in Xcode 8 beta – Swift and Apple LLVM Compilers: Swift Language
The
@noescape
and@autoclosure
attributes must now be written before the parameter type instead of before the parameter name. [SE-0049]
因此,您使用非默认 @escaping
属性如下;应用于闭包参数的类型,而不是参数本身
func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
// ...
}
(包括我在下面的评论中对一个问题的回答,因为评论不是关于 SO 的持久数据)
@Cristi Băluță: "What does escaping do? Never seen this keywords before swift3 auto-conversion ... "
参见例如link 到 SE-0103 evolution proposal above(以及 beta 6 发行说明中引用的文本):以前,闭包参数默认转义(因此不需要存在用于转义的显式注释) ,但现在默认情况下是非转义的。因此,添加 @escaping
以明确注释闭包参数可能会转义(与其默认行为相反)。这也解释了为什么 @noescape
现在已被弃用(无需注释默认行为)。
为了解释闭包参数转义的含义,我引用 Language Reference - attributes:
"Apply this attribute to a parameter’s type in a method or function declaration to indicate that the parameter’s value can be stored for later execution. This means that the value is allowed to outlive the lifetime of the call."
@noescape
来自 xcode 8 beta 6 @noescape
是默认值。在此之前,@escaping
是默认值。从以前的版本更新到 swift 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
的好处:
- 编译器可以优化您的代码以获得更好的性能
- 编译器可以负责内存管理
- 不需要在闭包中使用self的弱引用
有关详细信息,请查看:Make non-escaping closures the default