在表视图中异步加载图像

Loading images async in tableview

我写了一个异步方法来将图片加载到表视图中。但问题是图像没有加载,因为它不会在滚动后自动更新。我尝试添加:

tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.none)

但这只会一直用不同的图像刷新行。第二个问题是滚动后图像会显示,但有时图像会加载到错误的行中。

有人能帮我解决这个问题吗,因为我想不通。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "ArticleCell", for: indexPath)
     let article = newsArticles!.articles[indexPath.row]
        
     cell.textLabel?.text = article.title
     cell.detailTextLabel?.text = article.content
        
     cell.imageView?.image = nil
        
     if let url = article.urlToImage {
         imageLoader.obtainImageWithPath(imagePath: url) { (image) in
             if let updateCell = tableView.cellForRow(at: indexPath) {
                 updateCell.imageView?.image = image
                 tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.none)
             }
         }
     }
        
        
     return cell
}

图像加载器:

class ImageLoader {
    var imageCache = NSCache<NSString, UIImage>()
    
    init() {
        self.imageCache = NSCache()
    }
    
    func obtainImageWithPath(imagePath: URL, completionHandler: @escaping (UIImage) -> ()) {
        if let image = self.imageCache.object(forKey: imagePath.absoluteString as NSString) {
            DispatchQueue.main.async {
                completionHandler(image)
            }
        } else {
            let placeholder: UIImage = UIImage(named: "placeholderImage")!
            DispatchQueue.main.async {
                completionHandler(placeholder)
            }
            let task = URLSession.shared.dataTask(with: imagePath, completionHandler: {data, response, error in
                let image: UIImage! = UIImage(data: data!)
                self.imageCache.setObject(image, forKey: imagePath.absoluteString as NSString)
                DispatchQueue.main.async {
                    completionHandler(image)
                }
            })
            
            task.resume()
        }
    }
}

更新您的 ImageLoader 代码,让您检查图像是否已在缓存中并 return 同步给您。

然后你加载cell的时候,如果有图片,马上设置。如果它没有图像,则让完成处理程序在该索引路径处的单元格上重新加载。然后,由于图像现在已缓存,您的常规单元格加载代码将能够填充图像。只要确保您仅在尚未从缓存中设置图像时才请求该图像。

你现在的代码编写方式,无论它是否在你的完成处理程序中从缓存中设置图像,它都会无休止地尝试重新加载它刚刚设置图像的行,这也会产生影响表现。因此,正如我所说,为什么只有在刚刚下载了新图像时才应该重新加载单元格。并且不要在完成处理程序中设置图像,只需重新加载该行。