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.

Obteniendo el resultado de una API con clausura y pasándolo a otro ViewController.

Estoy obteniendo un resultado de API en mi viewModel de la siguiente manera:

class HomePageViewModel {

var apiResult: CountryDataFromAPI?

//Obteniendo el resultado de API a través del viewModel

public func getAPIResult(withOffset: Int, completion: @escaping () -> Void) {
APIHandler.urlRequest(with: withOffset) { result in
self.apiResult?.data.append(contentsOf: result.data)
print(“el resultado de la API en el viewModel es (result.data)”)
completion()
}
}
}

Obtener la API funciona bien. En el código anterior, puedo imprimir la declaración como print(“el resultado de la API en el viewModel es (result.data)”) y ver el resultado de la API esperado.

Cuando obtengo los datos dentro de mi viewModel como se muestra arriba, los uso en mi mainViewController.

Mi mainViewController se inicializa con el ViewModel

class HomePageViewController: UIViewController {

private var viewModel : HomePageViewModel
private var countryDataArray: [CountryData]?

init(with viewModel: HomePageViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
}

Todo funciona bien hasta que intento obtener los datos del viewModel como se muestra a continuación.
Estoy tratando de establecer los datos en el ViewModel en un parámetro llamado countryDataArray. Pero al hacerlo dentro de la clausura, mi declaración de impresión “print(“los datos en vc son (self?.viewModel.apiResult?.data)”)” imprime nil aunque obtenga los datos en el viewModel.

override func viewDidLoad() {
super.viewDidLoad()
//Obteniendo el resultado de la API en viewDidLoad. Y después de obtener el resultado, recargando la tableView.
self.viewModel.getAPIResult(withOffset: 11) { [weak self] in
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
self?.countryDataArray = self?.viewModel.apiResult?.data
print(“los datos en vc son (self?.viewModel.apiResult?.data)”)
self?.countriesListTableView.reloadData()
})
}
}

¿Por qué esto podría estar sucediendo?

PD: Mis modelos de API son los siguientes:

struct CountryDataFromAPI: Codable {
var data: [CountryData]
}

struct CountryData: Codable,Equatable {
let name : String
let code: String
let wikiDataId: String
}

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema podría estar relacionado con el cierre, capturando self como weak. Dado que self es opcional, se requiere el encadenamiento opcional para acceder a las propiedades viewModel y apiResult. En este caso, es posible que el encadenamiento opcional esté causando que countryDataArray sea nil, aunque los datos estén disponibles en el viewModel.

    Para solucionar el problema, intenta usar enlace opcional para desempaquetar de manera segura self antes de acceder a sus propiedades:

    self.viewModel.getAPIResult(withOffset: 11) { [weak self] in
        guard let self = self else { return }
        DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
            self.countryDataArray = self.viewModel.apiResult?.data
            print("los datos en la vista de controlador son \(self.viewModel.apiResult?.data)")
            self.countriesListTableView.reloadData()
        })
    }
    

    De esta manera, self se desempaqueta de manera segura y se puede utilizar sin encadenamiento opcional. Alternativamente, podrías usar encadenamiento opcional para desempaquetar de manera segura countryDataArray también:

    self.viewModel.getAPIResult(withOffset: 11) { [weak self] in
        DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
            self?.countryDataArray = self?.viewModel.apiResult?.data
            print("los datos en la vista de controlador son \(self?.viewModel.apiResult?.data)")
            self?.countriesListTableView.reloadData()
        })
    }
    

    De cualquier manera, debería resolver el problema y permitirte acceder a los datos en tu viewModel.

Comments are closed.