简体   繁体   中英

Best practices for downloading images in a UITableView's cells? iOS/Swift

So I had this argument at work about what's better for downloading images in a UITableView's cells.

The two options are: In the cellForRowAtIndex, I download the image asynchronously which leads to using multiple threads and multiple network requests which we suspect may be the issue for battery drain.

The other option is to download all the images at once using one thread and one network request, by looping through an array with all the images' URLs outside the cellForRowAtIndex of coarse, and then calling the the table view reload function.

There is also a slight modification for latter approach where we can set each image (perhaps by calling the reload function) as soon as each image is downloaded.

So I would love to know, what's the industry standard way of handling this? What are the pros and cons especially when it comes to performance? Are there any better ways?

I generally use SDWebImage , it caches the images and can be reused later. It provides flexibility with its extensions and various methods.

Check my implemented code:

import UIKit
import SDWebImage

extension AcceptedWinksViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: Constants.CellIdentifier.WinkListTableViewCell) as! WinkListTableViewCell
        let profile = self.winkList[indexPath.row] //Model
        let placeHolderImage = UIImage(named:"placeHolder") //your placeholder image, can be class or global variable
        if let url = profile.imageURL {
            cell.userImageView.sd_setImage(with: url, placeholderImage: placeHolderImage, options: .refreshCached, completed: nil) //check its various options
        }
        else {
            cell.userImageView.image = placeHolderImage
        }
        return cell
    }
}

Best practices are below for me;

  • If you have a lot of image/cell, lets say 1000, don't download all of them. User may not scroll to bottom. Only download visible cells.
  • After image is downloaded, check if cell is still visible. Tableview has a indexPathsForVisibleRows property which you can get all visible cell indexPaths. If cell is not visible, you should not attached the image.
  • You should obviously download them on background thread asynchronously. But you should limit the max concurrent operation count. You can do this with operation queues. Otherwise, if system will create a lot of threads (more than ideal), performance will be worse. I am not sure about the ideal count. Just try a few and compare the results.
  • You should cache the downloaded image and should not download again and again. Only download it once. You can use dictionary to cache them in memory.
  • After you downloaded image, attach it to the cell on main thread. Otherwise, it will be slower if you attach on background thread.
  • You can also implement cancellation mechanism. If cell becomes invisible, it is better to cancel the download. This can be done with Operations and Operation Queues. It is harder to do this with GCD.
  • Use placeholder image until you download the image.

For battery consumption;

Based on Apple's energy efficiency guide, it is better to download items in bulk compared to download one by one. But, there is a tread-off here. In my opinion, performance has the highest priority here compared to battery consumption.

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