我有一个从 API 下载 JSON 数据并将其设置在表格 View 单元格中的应用程序。在某些时候,通过在随机单元格图像中向上/向下滚动,在它具有正确的图像之前可能会自行更改几次。文本数据没有任何问题。起初我以为问题是单元格的可重用性,所以我需要在实际设置新图像之前销毁数据。所以我将 TableViewCell 的这种方法添加到 cellForRowAt 路径以在设置单元格之前销毁数据:
func destroyCellData() {
self.newsImageView.image = nil
self.newsTitleLabel.text = nil
self.tagLabel.text = nil
}
然后是设置单元格的实际方法:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "newscell") as? NewsTableViewCell else {
print("No such cell")
exit(14)
}
cell.loadingImageIndicator.startAnimating()
let data = dataManager.getData()
let dataToInsert = data[indexPath.row]
cell.destroyCellData()
cell.setDataToCell(with: dataToInsert)
return cell
}
方法 setDataToCell 是:
func setDataToCell(newsObject: jsonNews) {
self.newsTitleLabel.text = newsObject.title
self.tagLabel.text = newsObject.tag
let url = newsObject.imageURL
self.newsImageView.loadImageUsingCacheWithURLString(url, placeholder: UIImage(named: "ViewPlaceholder"), indicator: loadingImageIndicator)
}
最后我在单元格中异步加载图像:
let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
func loadImageUsingCacheWithURLString(_ URLString: String, placeholder: UIImage?, indicator: UIActivityIndicatorView? = nil) {
self.image = nil
if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
self.image = cachedImage
indicator?.stopAnimating()
return
}
guard let encodedString = URLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
print("Error Loading URL")
return
}
if let url = URL(string: encodedString) {
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
if error != nil {
print("ERROR LOADING IMAGES FROM URL: \(String(describing: error))")
OperationManager.UI {
self.image = placeholder
indicator?.stopAnimating()
}
return
}
if let data = data {
if let downloadedImage = UIImage(data: data) {
print(URLString)
imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
OperationManager.UI {
self.image = downloadedImage
indicator?.stopAnimating()
}
}
}
}).resume()
}
}
所以我的问题是 - 问题出在我下载和设置图像的方法上,还是出在单元的可重用性上?如果可能的话,给我一个更合适的方法来将图像设置为单元格的提示。提前致谢
最佳答案
如果没有您的代码,我怀疑您的问题可能与可重用单元格和异步图像下载有关。这样一来,当您重新加载单元格时,它会启动一个数据任务来下载图像,如果第二个任务开始下载不同的图像,则第一个任务不会发生任何事情。
例如,假设您的第一张图片为 100MB,可重复使用单元格的第二张图片为 1KB。希望 1KB 下载速度更快。这是流程
- 带有
image1
的称重传感器 - 开始下载
image1
- 带有
image2
的称重传感器 - 开始下载
image2
- 完成
image2
的下载 - 将单元格图像设置为
image2
- 完成下载
image1
- 将单元格图像设置为
image1
由于image2已经设置好,image1的数据下载任务已经完成,cell在显示image2后会更新显示image1,从而显示错误的图片。
要解决您的问题,您需要以某种方式取消第一个操作,或者更确切地说,如果不再显示该数据,则不更新 ImageView 。有很多方法可以做到这一点。一种解决方案是在您的单元格上创建图像 url 的属性,并在下载完成后确认其正确的 url,如果正确,则更新 ImageView 。
func setDataToCell(newsObject: jsonNews) {
// Your other code
self.imageURL = newsObject.imageURL
}
// loadImageUsingCacheWithURLString
if let downloadedImage = UIImage(data: data) {
print(URLString)
imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
OperationManager.UI {
if url.absoluteString == self.imageURL {
self.image = downloadedImage
indicator?.stopAnimating()
}
}
}
注意:没有测试任何这段代码,而是直接从我的脑海中写出来的。它可能有错误。
综上所述,我建议使用第三方图像缓存系统,如 AlamofireImage或人们评论过的其他人之一。
关于json - 从 TableView 中的 JSON 数据下载可重复使用的单元格或错误的异步图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46207630/