I basically want to have an optional completion handler that has no parameters that are passed back. Here is what I have so far but obviously it is wrong.
func refreshAccountData(type:String, completion: (()->(Void))?){
//Network call is made
Alamofire.request... {
completion?()
//Here is where I want to call the optional completion handler
}
}
I don't want to pass any parameters in the completion block. I just want to know when the network call has been completed so I can refresh the UI. I don't want to refresh the UI here because I want this to act as a generic function for refreshing data. The reason I want the completion handler to be optional is because sometimes I don't need to do anything after the refresh is done.
I am very confused about what @escaping means as well. I usually have it when I do things like this but any clarity would be great. I have done some homework about it online but not found much that I really get.
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()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With