可选的Completion Handler,没有参数

时间:2018-02-14 20:27:43

标签: swift swift4

我基本上希望有一个可选的完成处理程序,它没有传回的参数。这是我到目前为止所做的,但显然是错的。

func refreshAccountData(type:String, completion: (()->(Void))?){
    //Network call is made
    Alamofire.request... {
        completion?()
        //Here is where I want to call the optional completion handler
    }

}

我不想在完成块中传递任何参数。我只想知道网络调用何时完成,以便我可以刷新UI。我不想在这里刷新UI,因为我希望它作为刷新数据的通用功能。我希望完成处理程序是可选的原因是因为有时我不需要在刷新完成后做任何事情。

我对@escaping的含义感到非常困惑。当我做这样的事情时,我通常会拥有它,但任何清晰度都会很好。我已经在网上完成了一些关于它的功课,但没有找到我真正得到的。

1 个答案:

答案 0 :(得分:5)

首先,将括号放在Void类型:

周围
func refreshAccountData(type:String, completion: (() -> Void)?){
    //Network call is made
    Alamofire.request... {
        completion?() 
    }
}

如果你强制打开一个闭包调用,你基本上就是说你知道总会有一个完成回调。但在您的情况下,您明确提到您想要一个可选项,因此调用completion?()就是您想要的。

关于转义,可选闭包是隐式转义的,因此如果你想要一个非转义版本,你必须使用非可选闭包。阅读docs中的Escaping Closures部分,了解有关转义的更多信息。基本上,在您的情况下,您需要一个转义闭包,因为您在异步回调中使用completion,在<{em> refreshAccountData完成后执行。但是,正如我所说的那样,使闭包成为可选的隐藏式转义(在SO question中阅读更多内容)。

现在您知道您的completion正在逃避 - 这是什么意思?简单地说,如果它是非转义的,编译器将保证在completion方法完成后释放refreshAccountData闭包,因此实际上释放completion捕获的所有资源也是。然而,转义completion闭包可以在refreshAccountData调用期间延长 - 意味着它可以创建保留周期(闭包可能保持对self和其他对象的实时强引用是因为保留了。)

现在在你的情况下,既然你想要一个可选的completion闭包,除了简单地接受它是逃避之外别无他法 - 所以你怎么能确保completion闭包不会保持不需要的强烈的参考?您可以在创建完成时简单地使用捕获列表(请参阅this以获取参考),以确保偶数self只是一个弱引用,并且由于闭包而不会保留:

refreshAccountData(type: "") { [weak self] in
    guard let strongSelf = self else { return }
    strongSelf.doSomething()
}