Aqui está um trecho de código do meu SwiftUI ViewModel:
@Published var data: Data
@Published var showingAlert = false
func fetchData() {
Task {
let result = await NetworkManager.fetchData(),
await updateUI(with: result)
}
}
@MainActor
private func updateUI(with result: Result<Data, Error>) {
do {
data = try result.get()
} catch {
showingAlert = true
}
}
Não tenho certeza se esta é a abordagem idiomática (sou relativamente novo no SwiftUI), mas funciona muito bem.
Minha pergunta é:
podemos nos livrar de uma "espera" mesclando as linhas em uma única?
await updateUI(with: NetworkManager.fetchData())
Este código é equivalente ao anterior?
Mais importante ainda, preciso que a chamada de rede seja executada em um thread em segundo plano enquanto as atualizações da IU são executadas no thread principal. Este ainda é o caso aqui?
Como isso pode ser comprovado? (você sabe, na era GPT tudo deveria ser verificado 😂)
Sim, estes são equivalentes. Da proposta do Swift Evolution :
Contanto que
NetworkManager.fetchData()
não esteja isolado do ator principal, ele será executado em um thread não principal, pelo pool de threads cooperativo. Mesmo que seja isolado do ator principal, provavelmente você está utilizandoURLSession
APIs na sua implementação, que não são isoladas.Você pode ligar
MainActor.shared.assertIsolated()
paraNetworkManager.fetchData()
"provar" isso. Se esse método falhar, você não estará no ator principal.Parece que você está usando um
ObservableObject
para isso. Não há necessidadeObservableObject
apenas para esta operação assíncrona. Você pode mover tudo para o seu arquivoView
.Você pode então chamar isso em um modificador
.task { ... }
outask(id: something) { ... }
, que cancela a tarefa se a visualização desaparecer. No momento, vocêObservableObject
não lida com o cancelamento do nível superiorTask
que você criou.