当前位置: 首页 > 知识库问答 >
问题:

快速可选的转义闭合

司徒隐水
2023-03-14

编译器错误闭包使用非转义参数“完成”可能允许它转义,这是有意义的,因为它将在函数返回后调用。

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?()
    }
}

共有2个答案

梁丘高朗
2023-03-14

为了理解这种情况,实现以下代码将是有用的:

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 已经发布,如果默认情况下在枚举、结构或类中声明,则闭包将被“转义”。

作为参考,报告了与此问题相关的错误:

  • 可选的闭包类型始终被视为@escaping
  • @在可选块上转义失败

虽然他们可能与本案没有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)

既然你期望你必须让完成:(()-

单于翰飞
2023-03-14

将闭包包装在可选的文件中会自动将其标记为转义。从技术上讲,它已经通过嵌入到枚举中“转义”(可选)。

 类似资料:
  • 问题内容: 编译器错误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中做