I have a step function on AWS triggered by an HTTP Post request. The function can take a few seconds to complete. I'd like for execution to continue if the user puts the app into the background, and to correctly navigate to the next screen once the user puts the app back into the foreground (if execution has finished).
My API Client endpoint looks like this:
func connect<OutputType: Decodable>(to request: URLRequestConvertible, decoder: JSONDecoder) -> AnyPublisher<Result<OutputType, Error>, Never> {
var request = request.asURLRequest()
if let token: String = KeychainWrapper.standard.string(forKey: "apiToken") {
request.addValue(token, forHTTPHeaderField: "Authorization")
}
let configuration = URLSessionConfiguration.default
configuration.waitsForConnectivity = true
let session = URLSession(configuration: configuration)
return session.dataTaskPublisher(for: request)
.tryMap({ (data, response) -> Data in
guard let response = response as? HTTPURLResponse else { throw NetworkError.invalidResponse }
guard 200..<300 ~= response.statusCode else {
throw NetworkError.invalidStatusCode(statusCode: response.statusCode)
}
return data
})
.decode(type: OutputType.self, decoder: decoder)
.map(Result.success)
.catch { error -> Just<Result<OutputType, Error>> in Just(.failure(error)) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
I'd like to know the best practice for implementing this call. I'm currently using beginBackgroundTask below.
func makeRequest() {
DispatchQueue.global(qos: .userInitiated).async {
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Request Name") {
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
self.backgroundTaskID = .invalid
}
<implementation>
}
}
However, implementation
only works if I have nested DispatchQueue.main.async blocks where I perform more logic after making the HTTP request (like determining which screen to navigate to next after we receive the response.
Is this the best way to do it? Is it ok to have a few different nested DispatchQueue.main.async blocks inside the DispatchQueue.global block? Should I post the .receive(on: )
to DispatchQueue.global?