Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kingfisher image render recycling cells

I'm using Kingfisher to download and cache my images. I'm using the custom class below CustomImageView that extends ImageView. I also am using my custom UITableViewCell to call the loadImage method within the didSet property in my CustomCell class file.

The below method loadImage is where all the magic happens.

class CustomImageView : UIImageView {
var lastUrlLoaded: String?

func loadImage(url:String) {
    lastUrlLoaded = url
    ImageCache.default.retrieveImage(forKey: url, options: nil) { (image, cacheType) in
        if let image = image {
            self.image = image
            return
        }
        else {
            guard let url = URL(string: url) else { return }
            self.kf.setImage(with: url, placeholder: nil, options: nil, progressBlock: nil) {
                (image, error, cacheTye, _) in
                if let err = error {
                    self.kf.indicatorType = .none
                    DispatchQueue.main.async {
                      self.image = #imageLiteral(resourceName: "no_image_available") 
                    }
                    print ("Error loading Image:", err)
                    return
                }

                if url.absoluteString != self.lastUrlLoaded { return }
                if let image = image {
                    ImageCache.default.store(image, forKey: url.absoluteString)
                    DispatchQueue.main.async {
                        self.image = image
                    }
                }
            }
        }
    }
}

// Custom TableViewCell -- NewsCell.file
 class NewsCell: UITableViewCell {
var article: Article? {
    didSet{
        guard let image_url = article?.image_url else { return }
        _image.kf.indicatorType = .activity
        _image.loadImage(url: image_url, type: "news")
      }
   }
}

 // METHOD in my NewsController
 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: 
  IndexPath) -> UITableViewCell {        
   let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! NewsCell
      cell.article = articles[indexPath.item]
return cell
}

I'm having an issue when scrolling fast through my cells, some images that have loaded are being used for the wrong cells. I've researched and read other post but no answers helped me. I understanding it's dealing with the background task but just not sure how to fix it. If someone can help or point me in the right direction it would be much appreciated.

Solutions I've seen on stackoverflow and tried:

  1. prepareForReuse in custom cell setting the image to nil.
  2. setting the image to nil at cellforrowatindexpath.
like image 451
antdwash Avatar asked Nov 09 '17 04:11

antdwash


People also ask

What is Kingfisher and how does it work?

The most compelling feature of Kingfisher is caching. Each image is fetched once and that is why scrolling the table view is fast and performant. Kingfisher caches images in memory for fast access, but it also writes images to disk. Its behavior is similar to that of the ImageService class we created earlier in this series.

What is Kingfisher rendermix?

Kingfisher Rendermix is formulated specifically for use during rendering after the DPC injection process. Incorporating a powerful fungicide, this waterproof cement additive provides a great, smooth wall. Our waterproofing render mix also prevents further damaging fungal growth from occurring.

What is Kingfisher sample purification?

KingFisher Sample Purification Systems offer versatile laboratory benchtop automation for consistent extraction and purification of DNA, RNA, proteins, and cells.

Does kingfisher write images to disk or memory?

Kingfisher caches images in memory for fast access, but it also writes images to disk. Its behavior is similar to that of the ImageService class we created earlier in this series. Writing images to disk is useful to avoid fetching the same image every time the application launches.


Video Answer


1 Answers

override func prepareForReuse() {
    super.prepareForReuse()
    imageView.kf.cancelDownloadTask() // first, cancel currenct download task
    imageView.kf.setImage(with: URL(string: "")) // second, prevent kingfisher from setting previous image
    imageView.image = nil
}
like image 199
孫晧烜 Avatar answered Oct 10 '22 14:10

孫晧烜