我基本上希望有一个可选的完成处理程序,该处理程序没有传递回的参数。这是我到目前为止所拥有的,但显然是错误的。
func refreshAccountData(type:String, completion: (()->(Void))?){
//Network call is made
Alamofire.request... {
completion?()
//Here is where I want to call the optional completion handler
}
}
Run Code Online (Sandbox Code Playgroud)
我不想在完成块中传递任何参数。我只想知道网络通话何时完成,以便刷新UI。我不想在这里刷新UI,因为我希望它充当刷新数据的通用函数。我希望完成处理程序为可选的原因是,有时刷新完成后,我不需要执行任何操作。
我对@转义的含义也很困惑。当我做这样的事情时,我通常会拥有它,但是任何清晰度都会很棒。我已经在网上做了一些功课,但没有得到很多真正的收获。
首先,将方括号放在Void类型周围:
func refreshAccountData(type:String, completion: (() -> Void)?){
//Network call is made
Alamofire.request... {
completion?()
}
}
Run Code Online (Sandbox Code Playgroud)
如果您强制解开闭包调用,则基本上是在说您知道总会有一个完成回调。但是在您的情况下,您明确提到要使用可选内容,因此调用completion?()就是您想要的。
关于转义,可选的闭包会隐式地转义,因此,如果要使用非转义的版本,则必须使用非可选的闭包。阅读文档中的“转义闭包”部分,以了解有关转义的更多信息。基本上,就您而言,您需要一个转义的闭包,因为您使用completion了异步回调,该回调在完成后执行refreshAccountData。但是再次,正如我所说,将闭包设置为可选使其隐式转义(请参阅SO问题中的更多内容)。
现在您知道自己completion正在逃跑-这是什么意思?简而言之,如果非转义,编译器将保证completion在refreshAccountData方法完成后释放闭包,因此,实际上,completion也将释放由捕获的所有资源。completion但是,转义的闭包可以比refreshAccountData调用期间更长的寿命-这意味着它可以创建保留周期(闭包可能保持对self其他对象的有效强引用,这可能是因为保留了该对象)。
现在就您而言,既然您想要一个可选的completion闭包,您别无选择,只能简单地接受它的转义-那么如何确保completion闭包不会保留不需要的强引用?您可以在创建补全时简单地使用捕获列表(请参阅此作为参考),以确保甚至self只是一个弱引用,并且由于闭包而不会被保留:
refreshAccountData(type: "") { [weak self] in
guard let strongSelf = self else { return }
strongSelf.doSomething()
}
Run Code Online (Sandbox Code Playgroud)