I am making API calls and for that purpose I use completionHandlers in Swift. I came to issues where I need to call one function with completionHandler right after another one succeeds but the nested function is not called and main function does not return anything now.
Here is code:
func submit(completionHandler: @escaping (Result<MyResult, Error>) -> Void) {
submitSerice.subit() { [weak self] result in
switch result {
case .success(let submitResponse):
self?.getNextSession() { response in
switch sessionResponse {
case .success(let nextSession):
// do something and return submitResponse
completionHandler(.success(submitResponse))
case .failure(let error):
completionHandler(.failure(error))
}
}
case .failure(let error):
completionHandler(.failure(error))
}
}
}
func getNextSession(completionHandler: @escaping (Result<NextSession, Error>) -> Void) {
print("Calling getNextSession()")
nextSesssionService.nextSession() { result in
switch result {
case .success(let response):
completionHandler(.success(response))
case .failure(let error):
completionHandler(.failure(error))
}
}
}
When getNextSession and submit are called alone everything works fine but here print "Calling getNextSession()" is not even shown in terminal.
Given how you've written this, a likely cause is that
selfis deallocated between the time you callsubmitand the timesubmitSerice.subitcalls its completion handler. If you want to ensure that this operation completes, you should not use[weak self]here. You should hold a strong reference to ensure the operation completes. At a minimum, you should probably add logging ifselfis nil so that you know what's happened.That said, I highly recommend converting this to
async/await. The code to handle serial execution of asynchronous operations will be dramatically simpler than when using completion handlers.