Download and cache images in UITableViewCell

前端 未结 2 1493
遥遥无期
遥遥无期 2020-12-06 08:06

Note: Please no libraries. This is important for me to learn. Also, there are a variety of answers on this but none that I found solves the issue nicely. Please don\'t m

相关标签:
2条回答
  • 2020-12-06 08:50

    A couple of issues:

    1. One possible source of flickering is that while you're updating the image asynchronously, you really want to clear the image view first, so you don't see images for prior row of reused/dequeued table view cell. Make sure to set the image view's image to nil before initiating the asynchronous image retrieval. Or, perhaps combine that with "placeholder" logic that you'll see in lots of UIImageView sync image retrieval categories.

      For example:

      extension UIImageView {
      
          func setImage(from url: URL, placeholder: UIImage? = nil) {
              image = placeholder               // use placeholder (or if `nil`, remove any old image, before initiating asynchronous retrieval
      
              ImageCache.shared.image(for: url) { [weak self] result in
                  switch result {
                  case .success(let image):
                      self?.image = image
      
                  case .failure:
                      break
                  }
              }
          }
      }
      
    2. The other issue is that if you scroll very quickly, the reused image view may have an old image retrieval request still in progress. You really should, when you call your UIImageView category's async retrieval method, you should cancel and prior request associated with that cell.

      The trick here is that if you're doing this in a UIImageView extension, you can't just create new stored property to keep track of the old request. So you'd often use "associated values" to keep track of prior requests.

    0 讨论(0)
  • 2020-12-06 08:57

    Swift 3:

    Flickering can be avoided by this way:

    Use the following code in public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

    cell.photoImageView.image = nil //or keep any placeholder here
    cell.tag = indexPath.row
    let task = URLSession.shared.dataTask(with: imageURL!) { data, response, error in
        guard let data = data, error == nil else { return }
    
        DispatchQueue.main.async() {
            if cell.tag == indexPath.row{
                cell.photoImageView.image = UIImage(data: data) 
            }
        }
    }
    task.resume()
    

    By checking cell.tag == indexPath.row, we are assuring that the imageview whose image we are changing, is the same row for which the image is meant to be. Hope it helps!

    0 讨论(0)
提交回复
热议问题