Swift可选的转义闭包 [英] Swift optional escaping closure

查看:239
本文介绍了Swift可选的转义闭包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编译器错误Closure use of non-escaping parameter 'completion' may allow it to escape,之所以有意义,是因为它将在函数返回后被调用.

Compiler error Closure use of non-escaping parameter 'completion' may allow it to escape, Which make sense because it will be called after the function return.

func sync(completion:(()->())) {
    self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
        completion()
    }
}


但是,如果我将闭包设置为可选,则不会出现编译器错误,这是为什么呢?函数返回后仍可以调用闭包.


But if I make closure optional then no compiler error, Why is that? closure can still be called after the function returns.

func sync(completion:(()->())?) {
    self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
        completion?()
    }
}

推荐答案

说明:

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

Clarification:

For understanding the case, implementing the following code would be useful:

typealias completion = () -> ()

enum CompletionHandler {
    case success
    case failure

    static var handler: completion {
        get { return { } }
        set { }
    }
}

func doSomething(handlerParameter: completion) {
    let chObject = CompletionHandler.handler = handlerParameter
}

乍看之下,这段代码似乎合法,但事实并非如此!您会收到编译时错误提示:

At the first look, this code seems to be legal, but it's not! you would get compile-time error complaining:

错误:分配非转义 参数'handlerParameter'到一个@转义的闭包

error: assigning non-escaping parameter 'handlerParameter' to an @escaping closure

让chObject = CompletionHandler.handler = handlerParameter

let chObject = CompletionHandler.handler = handlerParameter

,并带有以下说明:

注释:参数'handlerParameter'是隐式的非转义函数 doSomething(handlerParameter:完成){

note: parameter 'handlerParameter' is implicitly non-escaping func doSomething(handlerParameter: completion) {

那是为什么?假设代码段与@escaping ...

Why is that? the assumption is that the code snippet has nothing to do with the @escaping...

实际上,由于Swift 3已发布,如果闭包在 enum struct class 中声明,则闭包将被转义"默认.

Actually, since Swift 3 has been released, the closure will be "escaped" if it's declared in enum, struct or class by default.

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

As a reference, there are bugs reported related to this issue:

  • Optional closure type is always considered @escaping.
  • @escaping failing on optional blocks.

尽管它们可能与本案并非100%相关,但受让人的评论清楚地描述了该案:

Although they might not 100% related to this case, the assignee comments are clearly describe the case:

第一条评论:

这里的实际问题是可选的闭包是隐式的 @立即转义.

The actual issue here is that optional closures are implicitly @escaping right now.

第二条评论:

不幸的是,Swift 3就是这种情况. 在Swift 3中逃脱

That is unfortunately the case for Swift 3. Here are the semantics for escaping in Swift 3:

1)函数参数位置的闭包为 默认情况下不转义

1) Closures in function parameter position are non-escaping by default

2)所有其他闭包都在转义

因此,所有通用类型参数闭包(例如Array和 Optional )都在转义.

Thus, all generic type argument closures, such as Array and Optional, are escaping.

很明显,Optional是枚举.

Obviously, Optional is enum.

同样-如上所述,相同的行为也适用于类和结构:

Also -as mentioned above-, the same behavior would be applicable for the classes and structs:

课堂案例:

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

以上两个代码段将导致相同的输出(编译时错误).

The two above code snippets would leads to the same output (compile-time error).

要解决此问题,您需要使函数签名为:

func doSomething( handlerParameter: @escaping completion)


由于您期望必须让completion:(()->())?转义,所以会自动完成-如上所述-.

Since you are expecting that you have to let the completion:(()->())? to be escaped, that would automatically done -as described above-.

这篇关于Swift可选的转义闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆