ios - 如何使用 UIImageView Extension 与 Swift 异步加载图像并防止重复图像或错误图像加载到单元格中

标签 ios swift uiimageview urlsession kingfisher

我正在 Swift 4 中开发一个图像加载库,例如 Kingfisher带有一些扩展来支持将图像从 URL 加载到 UIImageView 中。

那么我就可以在 UICollection 或 UITableview 单元格上使用这个扩展,并使用如下所示的 UIImageView :

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: 
  "collectioncell", for: indexPath)

    if let normal = cell as? CollectionViewCell {
    normal.imagview.loadImage(fromURL:imageURLstrings[indexPath.row])
  }

基本上这是我的扩展代码,实现基本的 URLSession dataTask 和缓存

public extension UIImageView {
public func loadImage(fromURL url: String) {
    guard let imageURL = URL(string: url) else {
        return
    }

    let cache =  URLCache.shared
    let request = URLRequest(url: imageURL)
    DispatchQueue.global(qos: .userInitiated).async {
        if let data = cache.cachedResponse(for: request)?.data, let 
           image = UIImage(data: data) {
             DispatchQueue.main.async {
                self.image = image
            }
        } else {
            URLSession.shared.dataTask(with: request, 
       completionHandler: { (data, response, error) in

            print(response.debugDescription)
                print(data?.base64EncodedData() as Any)
                print(error.debugDescription)
                if let data = data, let response = response, ((response as? HTTPURLResponse)?.statusCode ?? 500) < 300, let image = UIImage(data: data) {
                    let cachedData = CachedURLResponse(response: response, data: data)
                    cache.storeCachedResponse(cachedData, for: request)
                    DispatchQueue.main.async {
                       self.image = image
                    }
                }
            }).resume()
        }
    }
}



 }

结论是,有时我发现如果我的 URL 损坏或出现 404 错误,或者即使我在所有图像完全下载之前滚动 UICollectionView,图像也会加载到错误的单元格中,或者我有时会在 collectionView 中找到重复的图像,但这如果我使用 Kingfisher,则不会发生。

This is my results

This is kingfishers

如何防止我的扩展程序将错误的图像加载到单元格中或重复图像?

最佳答案

您正在异步更新 ImageView ,无论 ImageView 是否已被另一个单元格重复使用。

当你开始一个新的 ImageView 请求时,假设你没有立即在缓存中找到图像,那么在开始网络请求之前,你应该 (a) 删除任何先前的图像(就像布兰登建议的那样); (b) 可能加载占位符图像或 UIActivityIndi​​catorView; (c) 取消对该 ImageView 的任何先前图像请求。只有这样您才可以开始新的请求。

就如何在扩展程序中保存对先前请求的引用而言,您无法添加存储的属性,但可以使用 objc_setAssociatedObject要在启动 session 时保存 session 任务,请在请求完成时将其设置为 nil,并且 objc_getAssociatedObject当检索 session 对象以查看是否需要取消前一个 session 对象时。

(顺便说一句,Kingfisher 将此关联的对象逻辑包装在其 computed property for the task identifier 中。这是保存和检索此任务标识符的好方法。


就失败的请求而言,您执行无限制的图像请求可能会导致该问题。稍微滚动一下,您的请求就会积压并超时。取消(见上文)将减少该问题,但最终仍可能发生。如果修复上述问题后请求仍然失败,那么您可能需要限制并发请求的数量。常见的解决方案是将请求包装在异步 Operation 子类中,并使用 maxConcurrentOperationCount 将它们添加到 OperationQueue 中。或者,如果您正在寻找一种廉价且令人愉快的解决方案,您可以尝试提高请求中的超时阈值。

关于ios - 如何使用 UIImageView Extension 与 Swift 异步加载图像并防止重复图像或错误图像加载到单元格中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56094935/

相关文章:

ios - 关联的枚举类型实现 CaseItratable

ios - Swift - 在 NSArchiving 数组之前重置突变属性

iOS - UIImage 调整到更大变得模糊

swift - 如何在单元格之间获得更均匀的垂直距离?

ios - 如何使用 Eureka 表单从更改文本字段的行中检索值?

ios - 如何让我的应用程序在 iPhone 4 和 iPhone 5 屏幕上运行?

ios - 在 UIImageView 的右上角添加 UIButton

ios - imageview 未相应更新

ios - 核心数据 : statement is still active

ios - 通用 RawRepresentable 协议(protocol)属性