He estado probando la funcionalidad asíncrona/en espera vista previa en la versión Swift 5.5, pero no puedo recopilar los resultados de una función asíncrona y mostrarlos usando SwiftUI. Aquí está mi código:
import SwiftUI struct AsyncTestView: View { @State var text: String? // Async function func asyncGetText() async -> String { Thread.sleep(forTimeInterval: 10) return "My text" } // Stores the result of async function func fetchText() async { let text = await asyncGetText() DispatchQueue.main.async { self.text = text } } var body: some View { Text(text ?? "Loading") .onAppear(perform: fetchText) } }
Esto da como resultado el siguiente error:
llamada 'asincrónica' en una función que no admite concurrencia
Agregue 'async' a la función 'fetchText ()' para que sea asíncrona
Agregar async
a la función fetchText()
da como resultado el siguiente error en la función .onAppear()
:
Conversión no válida de la función 'async' del tipo '() async -> ()' al tipo de función síncrona '() -> Void'
En este artículo , usan la etiqueta @asyncHandler
para anotar la función fetchText
; sin embargo, esto da como resultado la advertencia: '@asyncHandler' has been removed from the language'
.
Soy el autor del artículo al que haces referencia.
Como se discutió en Descubrir la concurrencia en SwiftUI , las vistas pueden hacer uso de los nuevos .task { }
y .refreshable { }
para obtener datos de forma asíncrona.
Así que ahora tiene las siguientes opciones para llamar a su código asíncrono:
func someSyncMethod() { doSomeSyncWork() Task { await methodThatIsAsync() } }
List { } .task { await methodThatIsAsync() }
List { } .refreshable { await methodThatIsAsync() }
Si usa un modelo de vista independiente, asegúrese de marcarlo como @MainActor
para garantizar que las actualizaciones de propiedades se ejecuten en el actor principal.
Actualicé el código de mi artículo: https://github.com/peterfriese/Swift-Async-Await-Experiments
Según la nueva información en la sesión WWDC Meet async/await en Swift WWDC , a las 23:28, esto ahora se hace usando:
async { someState = await someAsyncFunction() }
Captura de pantalla de la sesión.
Estoy de acuerdo con la respuesta de @peter-friese, pero agregaré para aquellos que lean esto el cambio de sintaxis al pasar de sincronización a sincronización:
La nueva sintaxis:
Task { someState = await someAsyncFunction() }
Reemplaza esta sintaxis:
async { someState = await someAsyncFunction() }
... y el inicializador Task()
puede aceptar un parámetro de prioridad:
Task(priority: .userInitiated) { someState = await someAsyncFunction() }
import SwiftUI struct AsyncTestView: View { @State var text = "Loading" // Async function func asyncGetText() async -> String { try? await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC) return "My text" } var body: some View { Text(text) .task { text = await asyncGetText() } } }