翠鸟图像渲染回收单元

ant*_*ash 3 uitableview ios uicollectionviewcell swift kingfisher

我正在使用Kingfisher下载和缓存我的图像。我正在使用CustomImageView下面的自定义类来扩展ImageView。我还使用我的自定义UITableViewCell在CustomCell类文件中的didSet属性内调用loadImage方法。

下面的方法loadImage是发生所有魔术的地方。

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
}
Run Code Online (Sandbox Code Playgroud)

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.

小智 7

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
}
Run Code Online (Sandbox Code Playgroud)


小智 5

问题

快速滚动时,您正在重用单元格。重用的单元格包含KF图像,该图像可能具有正在运行的下载任务(从对kf.setImage的调用开始),用于回收物品中的图像。如果该任务被允许完成,它将使用旧图像更新您的新单元格。我将提出两种修复方法。

答案1-杀死回收的下载任务

请参阅Kingfisher备忘单,取消下载任务

备忘单显示了如何在表视图的didEndDisplaying中停止这些任务。我在这里引用:

// In table view delegate
func tableView(_ tableView: UITableView, didEndDisplaying cell: 
UITableViewCell, forRowAt indexPath: IndexPath) {
    //...
    cell.imageView.kf.cancelDownloadTask()
}
Run Code Online (Sandbox Code Playgroud)

您可以在那里或在单元格类的didSet观察器中进行操作。你明白了。

答案2-不要杀死他们,只是忽略结果

另一种方法是允许下载任务完成,但是仅当下载的URL与当前所需的URL匹配时才更新单元格图像。也许您正在尝试使用lastUrlLoaded实例变量执行类似的操作。

您可以在kf.setImage的完成处理程序中找到它:

if url.absoluteString != self.lastUrlLoaded { return }
Run Code Online (Sandbox Code Playgroud)

这是我的意思,除了您没有正确设置该变量以使其起作用。为了说明起见,我们假设它被称为“ desiredURL”。然后,您可以在didSet观察器中进行设置:

_image.desiredURL = image_url
Run Code Online (Sandbox Code Playgroud)

并在kf.setImage的完成处理程序中对其进行测试:

// phew, finished downloading, is this still the image that I want?
if url != self.desiredURL { return }
Run Code Online (Sandbox Code Playgroud)

笔记

如果是我,我肯定会选择第二种方法(它具有缓存下载图像的积极作用,但我也不相信取消任务)。

另外,似乎您正在尝试尝试kf.setImage为您完成的艰苦工作,即加载缓存等。我确定您有这样做的理由,无论哪种方式,您仍然需要处理问题。