编译器错误闭包使用非转义参数“完成”可能允许它转义
,这是有意义的,因为它将在函数返回后调用。
func sync(completion:(()->())) {
self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
completion()
}
}
但如果我将闭包设置为可选的,那么没有编译器错误,这是为什么?在函数返回后仍然可以调用闭包。
func sync(completion:(()->())?) {
self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
completion?()
}
}
为了理解这种情况,实现以下代码将是有用的:
typealias completion = () -> ()
enum CompletionHandler {
case success
case failure
static var handler: completion {
get { return { } }
set { }
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler.handler = handlerParameter
}
这个代码乍一看好像是合法的,其实不是!您会得到编译时错误抱怨:
错误:将非转义参数“handlerParameter”赋给@escaping闭包
对象CompletionHandler.handler
注意:
注意:参数“handlerParameter”是隐式非转义func do something(handler parameter:completion){
这是为什么呢?假设代码片段与< code>@escaping无关...
实际上,由于 Swift 3 已经发布,如果默认情况下在枚举、结构或类中声明,则闭包将被“转义”。
作为参考,报告了与此问题相关的错误:
虽然他们可能与本案没有100%的关联,但受让人的意见清楚地描述了本案:
第一条评论:
这里的实际问题是可选闭包现在隐式地@转义。
第二条评论:
不幸的是,Swift 3的情况就是这样。以下是Swift 3中转义的语义:
1)函数参数位置的闭包默认为非转义
2)所有其他闭包都在逃逸
因此,所有泛型类型参数闭包(如 Array 和 Optional)都是转义的。
显然,可选
是枚举。
同样,如上所述,相同的行为也适用于类和结构:
类别案例:
typealias completion = () -> ()
class CompletionHandler {
var handler: () -> ()
init(handler: () -> ()) {
self.handler = handler
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
结构案例:
typealias completion = () -> ()
struct CompletionHandler {
var handler: completion
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
上述两个代码段将导致相同的输出(编译时错误)。
为了修复这种情况,您需要让函数签名为:
func doSomething( handlerParameter: @escaping completion)
既然你期望你必须让完成:(()-
将闭包包装在可选的文件中会自动将其标记为转义。从技术上讲,它已经通过嵌入到枚举中“转义”(可选)。
问题内容: 编译器错误Closure use of non-escaping parameter ‘completion’ may allow it to escape,这是有道理的,因为它将在函数 返回之后被调用。 但是,如果我将闭包设为可选,则不会出现编译器错误,那是为什么呢? 函数返回后仍可以调用闭包。 问题答案: Clarification: 为了理解这种情况,实现以下代码将很有用: 乍一
问题内容: 我试图在Swift中声明一个需要可选闭包的参数。我声明的函数如下所示: 但是Swift抱怨说,“条件”中的绑定值必须是一个可选类型,其中声明了“ if let”。 问题答案: 您应该将可选的闭包括在括号中。这将适当地限制操作员的范围。
问题内容: 鉴于: 有什么方法可以使参数(和)的类型也保持不变? 更改类型会出现以下错误: @escaping属性仅适用于函数类型 删除该属性后,代码将编译并运行,但由于闭包使函数的作用范围变大,因此似乎并不正确。 问题答案: 有一个SR-2552报告无法识别功能类型别名。这就是错误的原因。您可以通过扩展函数签名中的函数类型来解决: 编辑1 : 我实际上是在xcode 8 beta版本下,但尚未解
问题内容: (这是该问题的后续内容: 使用具有多个键的可解码协议。) 我有以下Swift代码: 我知道,如果我使用并且没有该属性,但如果它是一个可选变量,它仍然可以正确处理它。 例如,以下JSON可使用上面的代码来解析它。 以下JSON也适用。 但是以下操作无效。 如何使所有3个示例正常工作?有什么类似的? 问题答案: 您可以使用以下功能: 返回一个值,该值指示解码器是否包含与给定密钥关联的值。与
鉴于: 有什么方法可以使类型的参数(和)并且还保留? 更改类型会产生以下错误: @escaping属性仅适用于函数类型 删除属性,代码将编译并运行,但似乎不正确,因为闭包正在转义函数的范围。
我正在尝试在我的Swift应用程序中创建一个服务对象,以便更轻松地处理请求。我已经把它连接起来了,但是我可能误解了完成处理器。 我有这个函数,它只是发布到我正在运行的本地APIendpoint。 我需要做的就是把这个名字传给我在这里做的函数 但是,我现在收到此错误。 调用中缺少参数“completion”的参数 我的目标是返回< code>Response对象,这样我就可以访问它的属性,在UI中做