I'm trying to display images that comes from an API. The images are inside an URL and I want to fill a Table View with all the array, but it shows only one image at the Table View.
Here's my code:
struct Autos {
let Marca:String
let Modelo:String
let Precio:String
let RutaImagen:String
init?(_ dict:[String:Any]?){
guard let _dict = dict,
let marca=_dict["Marca"]as?String,
let modelo=_dict["Modelo"]as?String,
let precio=_dict["Precio"]as?String,
let rutaImagen=_dict["RutaImagen"]as?String
else { return nil }
self.Marca = marca
self.Modelo = modelo
self.Precio = precio
self.RutaImagen = rutaImagen
}
}
var arrAutos = [Autos]()
func getImage(from string: String) -> UIImage? {
// Get valid URL
guard let url = URL(string: string)
else {
print("Unable to create URL")
return nil
}
var image: UIImage? = nil
do {
// Get valid data
let data = try Data(contentsOf: url, options: [])
// Make image
image = UIImage(data: data)
}
catch {
print(error.localizedDescription)
}
return image
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 9
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "carsCell", for: indexPath) as! CarsDetailTableViewCell
let url = URL(string: "http://ws-smartit.divisionautomotriz.com/wsApiCasaTrust/api/autos")!
let task = URLSession.shared.dataTask(with: url) {
(data, response, error) in
guard let dataResponse = data, error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}
do {
let jsonResponse = try JSONSerialization.jsonObject(with: dataResponse, options: []) as? NSArray
self.arrAutos = jsonResponse!.compactMap({ Autos($0 as? [String:String])})
DispatchQueue.main.async {
// Get valid string
let string = self.arrAutos[indexPath.row].RutaImagen
if let image = self.getImage(from: string) {
// Apply image
cell.imgCar.image = image
}
cell.lblBrand.text = self.arrAutos[indexPath.row].Marca
cell.lblPrice.text = self.arrAutos[indexPath.row].Precio
cell.lblModel.text = self.arrAutos[indexPath.row].Modelo
}
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
return cell
}
The JSON serialization is working fine, because the other data is showed correctly at the table view, the issue is with the image, because in the table view only appears one image, the other rows are empty. Does anyone have an advise?
I think you should download your full data before loading tableview and reload tableview in the completion handler. Call loadData()
method in your viewDidLoad()
.
fileprivate func loadData() {
let url = URL(string: "http://ws-smartit.divisionautomotriz.com/wsApiCasaTrust/api/autos")!
let task = URLSession.shared.dataTask(with: url) {
(data, response, error) in
guard let dataResponse = data, error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}
do {
let jsonResponse = try JSONSerialization.jsonObject(with: dataResponse, options: []) as? NSArray
self.arrAutos = jsonResponse!.compactMap({ Autos($0 as? [String:String])})
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
For loading images in tableView cell, download the image in background
thread and then update the imageView in the main
thread.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "carsCell", for: indexPath) as! CarsDetailTableViewCell
// Get valid string
let string = self.arrAutos[indexPath.row].RutaImagen
//print(string)
cell.lblBrand.text = self.arrAutos[indexPath.row].Marca
cell.lblPrice.text = self.arrAutos[indexPath.row].Precio
cell.lblModel.text = self.arrAutos[indexPath.row].Modelo
let url = URL(string: string)
if url != nil {
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
if data != nil {
cell.imgCar.image = UIImage(data:data!)
}
}
}
}
return cell
}
Hope this will work.