Cuando no quieres aislar toda la clase al hilo principal, puedes anotar solo los métodos que actualizan la UI:
class Descargador {
func descargar(url: URL) async throws -> Data {
let (data, _) = try await URLSession.shared.data(from: url)
await actualizarUI(datos: data)
return data
}
@MainActor
private func actualizarUI(datos: Data) {
// seguro en el hilo principal
}
}
MainActor.run
Task {
let datos = try await Descargador().descargar(url: url)
await MainActor.run {
label.text = "(datos.count) bytes descargados"
}
}
Swift 6 y concurrencia estricta
Con Swift 6, el compilador verifica en tiempo de compilación que el código de UI se llama siempre desde el hilo principal. Activar SWIFT_STRICT_CONCURRENCY = complete en Xcode muestra estos avisos antes de migrar a Swift 6.
