Tengo el siguiente código en Swift 5.5 y iOS 15
func getReviewIds() { var reviewIds: [Int] = [] Task { let ids = await getReviewIdsFromGoogle() reviewIds.append(contentsOf: ids) } print("outside") } func getReviewIdsFromGoogle() async -> [Int] { await withUnsafeContinuation { continuation in DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { continuation.resume(returning: [1,2,3]) } } }Recibo un error en la función getReviewIds en la siguiente línea:
reviewIds.append(contentsOf: ids) Mutation of captured var 'reviewIds' in concurrently-executing codeSé que puedo hacer que getReviewId sea una función asíncrona en lugar de usar el cierre asíncrono, pero ¿cómo puedo resolver esto usando el cierre?
No puede devolver datos al contexto sincrónico original una vez que haya iniciado un contexto asincrónico, ya que esto requeriría que el contexto original se "bloquee" mientras espera los resultados asincrónicos. Swift no permite el bloqueo en su modelo de concurrencia, ya que esto podría provocar un punto muerto en el subproceso.
Tendrá que llamar a otra función con los resultados del contexto de la Task para procesar los valores devueltos. Depende de usted si este proceso es otra función async o no, según lo que necesite hacer.
func getReviewIDs() { Task { let result = await getReviewIdsFromGoogle() process(ids: result) } } func process(ids: [Int]) { print("now process ids: \(ids)") } func getReviewIdsFromGoogle() async -> [Int] { await withUnsafeContinuation { continuation in DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { continuation.resume(returning: [1,2,3]) } } }Para evitar las carreras de datos, debe usar el acceso sincronizado a las variables de las operaciones concurrentes y el compilador no le permite cambiar su matriz directamente. Para evitar el problema, puede implementar un acceso aislado a sus datos con una instancia de actor , por ejemplo:
actor Store { var reviewIds: [Int] = [] func append(ids: [Int]) { reviewIds.append(contentsOf: ids) } } func getReviewIds() { let store = Store() Task { let ids = await getReviewIdsFromGoogle() await store.append(ids: ids) print(await store.reviewIds) } }