2

Im downloading the image link from a json and then creating the image once the table view start creating its cells:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCellController

            DispatchQueue.main.async(execute: { () -> Void in

                if let url = NSURL(string: self.movies[indexPath.row].image) 
                {

                    if let data = NSData(contentsOf: url as URL)
                    {
                        let imageAux = UIImage((data: data as Data))
                        cell.movieImage.image = imageAux
                        self.tableView.reloadData()

                    }
                }
            })

        cell.name = self.movies[indexPath.row].name
        cell.date = self.movies[indexPath.row].date
        return cell
}

And this works fine, but the table view becomes really slow, not at rendering but at scrolling. I keep checking the RAM and CPU and both are really low but my network use keeps rising BUT the images are already on the cell so it means its already done. (For this test im calling the JSON for only 2 movies, so 2 images)

Before i started doing this my total download was about 200kb (with images), now its getting over 2MB before i stop the project.

What im doing wrong?

Adrian
  • 315
  • 2
  • 3
  • 17

1 Answers1

5

You'll probably want to designate a separate queue for background activities. In this instance, your heavy network task is in:

NSData(contentsOf: url as URL)

This is what is "freezing" the UI. The best solution would be to define something like DispatchQueue.background and perform the network calls there, while then later performing the UI tasks back on the main thread so as not to lock up your display:

DispatchQueue.background.async(execute: { () -> Void in
    if let url = NSURL(string: self.movies[indexPath.row].image)  {
        //Do this network stuff on the background thread
        if let data = NSData(contentsOf: url as URL) {
            let imageAux = UIImage(data: data as Data)
            //Switch back to the main thread to do the UI stuff
            DispatchQueue.main.async(execute: { () -> Void in
                cell.movieImage.image = imageAux
            })
        }
    }
})

Let me know if this makes sense.

Michael Fourre
  • 3,005
  • 3
  • 15
  • 26
  • Thanks a lot! Another problem was that i didn't need to reload table, with it the images were downloading dozen of times (kind obvious but i didn't see it at first). Thanks a lot Michael! – Adrian Jan 23 '17 at 20:02
  • Michael Fourre i know this was not the question but i realize that i have a problem, since im using dequeueReusableCell everytime i scroll up or down the cell will download the images again, how could i avoid that? Thanks! – Adrian Jan 23 '17 at 20:13
  • 2
    I would cache the images @Adrian look into the `NSCache` documentation. It's quite easy to use. If you post another question I could add a snippet of my UIImage caching code as an example – Michael Fourre Jan 23 '17 at 21:05
  • Yeah thats pretty much the solution. I still have a minor problem but everything is working awesome. Thanks for the help, Michael – Adrian Jan 24 '17 at 03:25