Migrando seu Completion Handler para Async await
Com a evolução do iOS e do Swift ficou muito mais fácil fazer chamadas assíncronas e quando você precisa usar um código legado em uma nova tecnologia?

Códigos legados em swift na maioria das vezes utilizam o Completion Handler para realizar alguma tarefa assíncrona e notificar quem está chamando de que a operação foi realizada e que o e dados está pronto para ser retornado. Observando o código abaixo:
struct Joke: Decodable {
let icon_url: String
let value: String
}
func fetchRandomJoke(completion: @escaping (Joke?) -> Void) {
let url = URL(string: "https://api.chucknorris.io/jokes/random")!
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
if let messages = try? JSONDecoder().decode(Joke.self, from: data) {
completion(messages)
return
}
}
completion(nil)
}.resume()
}
O código acima está escrito da maneira "antiga" de como fazíamos requests em Swift.
Vamos supor que você está desenvolvendo uma nova feature em SwiftUI que vai utilizar a mesma request fecthRandomJoke que outras feature legadas utilizam, você pode acabar com alguns problemas:
Async/Await tem alguns comportamentos estranhos rodando com CompletionHandler
Pode pensar em criar 2 requests uma nova e outra legada o problema seria se o modelo mudasse com alguma frequência, você teria que alterar em 2 lugares
Você pode editar o código legado para usar o Async/Await mas provavelmente teria que mudar em vários lugares porque o código legado estará todo em CompletionHandler
Existe salvação?
Claro! Se você pensou em criar 2 requests você quase acertou o Swift nos permite utilizar uma função chamada withCheckedContinuation para fazermos essa alteração. Veja o código a seguir:
struct Joke: Decodable {
let icon_url: String
let value: String
}
func fetchRandomJoke(completion: @escaping (Joke?) -> Void) {
let url = URL(string: "https://api.chucknorris.io/jokes/random")!
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
if let messages = try? JSONDecoder().decode(Joke.self, from: data) {
completion(messages)
return
}
}
completion(nil)
}.resume()
}
func fetchRandomJoke() async -> Message? {
await withCheckedContinuation { continuation in
fetchRandomJoke { joke in
continuation.resume(returning: joke)
}
}
}
let joke = await fetchRandomJoke()
print(joke.value)
Dessa maneira mantemos somente uma request então o problema de alterar em dois lugares foi solucionado e agora você pode utilizar o novo jeito do Swift para lidar com chamadas assíncronas.






