es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El controlador de finalización siempre devuelve un array vacío, excepto cuando es llamado desde el código que popula el array.

Estoy teniendo algunas dificultades con el controlador de finalización. No quiero usar la nueva función async / await hasta aprender la forma antigua.

Esta es mi función fetch() con @escaping:

func fetch(completion: @escaping (Result<[CountriesFinal], CountryError>) -> Void) {
let urlString = “https://raw.githubusercontent.com/fdsfdghjfvghdfhf.json”

let url = URL(string: urlString)!

let _ = URLSession.shared.dataTask(with: url) { data, _, _ in
guard let jsonData = data else {
completion(.failure(.noDataAvailable))
return
}
do {
let decoder = JSONDecoder()
let countriesResponse = try decoder.decode(Country.self, from: jsonData)
let countryDetails = countriesResponse.countries
completion(.success(countryDetails))

} catch {
completion(.failure(.canNotProcessData))
}
}.resume()
}

He aprendido que fetch() debe ser llamado de esta forma dentro de viewDidLoad():

// var countriess = CountriesFinal // fuera de viewDidLoad

fetch { result in
switch result {
case let .failure(error):
print(error)
case let .success(holidays):
self.countriess = holidays
print(self.countriess[0].name) // FUNCIONA ✔️

}
}
// Si se escribe aquí o en cualquier otra función:
print(self.countriess[0].name) // Thread 1: Fatal error: Index out of range

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Respuesta del Experto en IT

    Parece que estás experimentando un problema relacionado con el tiempo de tu código asíncrono. El controlador de finalización que estás utilizando es un cierre de escape que se llama después de que se completa la solicitud de red. Esto significa que tu función fetch devuelve inmediatamente y el resto de tu código sigue ejecutándose mientras se realiza la solicitud de red.

    Cuando intentas acceder a self.countriess inmediatamente después de llamar a la función fetch, es posible que los datos aún no se hayan cargado, lo que hace que aparezca un error de “Índice fuera de rango”.

    Para solucionarlo, debes acceder a self.countriess solo dentro del controlador de finalización después de haber recibido una respuesta exitosa del servidor. Esto garantiza que los datos se hayan cargado antes de intentar acceder a ellos.

    Si necesitas acceder a self.countriess desde otra función o parte de tu código, debes asegurarte de hacerlo solo después de que se haya llamado al controlador de finalización y se hayan cargado los datos.

    Alternativamente, puedes usar un DispatchGroup para sincronizar tu código y esperar a que se complete la solicitud de red antes de continuar. Sin embargo, esto puede hacer que tu código sea más complejo y difícil de leer.

    En cuanto a la función async/await, es una forma más nueva de manejar el código asíncrono que facilita la escritura y la lectura. Sin embargo, si quieres aprender primero la forma antigua, eso está perfectamente bien. Solo asegúrate de ser consciente de los posibles problemas y de manejar tu código asíncrono correctamente.

Comments are closed.