简体   繁体   中英

I'm having troubles displaying an image from JSON in a Table View

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM