First, drop the brackets around Void
type:
func refreshAccountData(type:String, completion: (() -> Void)?){
//Network call is made
Alamofire.request... {
completion?()
}
}
If you force unwrap a closure call, you are basically saying that you know that there will always be a completion callback. But in your case you explicitly mentioned that you want an optional, so calling completion?()
is what you want.
Regarding escaping, optional closures are implicitly escaped, so if you want a non-escaping version, you would have to use non-optional closure. Read the Escaping Closures section in docs to learn more about escaping. Basically, in your case you need an escaping closure, because you use completion
in the asynchronous callback, which executes after the refreshAccountData
finishes. But again, as I said, making the closure optional makes it implicitly escaping (read more in SO question).
Now you know that your completion
is escaping - what does it mean? Simply put, if it is non-escaping, compiler will guarantee that the completion
closure gets released after the refreshAccountData
method finishes, thus in effect all the resources captured by the completion
would be released, too. Escaping completion
closure however can live longer that during the refreshAccountData
call - meaning that it can possible create retain cycles (the closure might be keeping live strong references to self
and other objects, which might be because of that retained).
Now in your case, since you want an optional completion
closure, you have no other way than simply to accept it is escaping - so how can you make sure completion
closure won't keep unwanted strong references? You can simply use capture list (see this for reference) when creating the completion to make sure that even self
is just a weak reference and it won't be retained because of the closure:
refreshAccountData(type: "") { [weak self] in
guard let self = self else { return }
self.doSomething()
}
completion?()
. I believe Xcode makes me for unwrap thecompletion!()
– Notepaperfunc refreshAccountData(type:String, completion: @escaping ()->()){
and just callcompletion()
? If you don't want to execute anything just pass am empty closure when calling your method – Sultanfunc refreshAccountData(type:String, completion: @escaping (()->()) = {}){
– Sultan