ios - 异步下载图像时, Collection View 单元格中的图像不会更新

标签 ios swift

从服务器下载图像时, Collection View 单元格中的图像不会更新。滚动 Collection View 时图像会更新。

TableView 的每个部分都有一个 Collection View 。表格 View 单元格具有 Collection View 的数据源。

extension OffersCell: UICollectionViewDataSource,UICollectionViewDelegate{
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        return photoViewModel.photos.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath)
        (cell as! PhotoCell).imageView.contentMode = .scaleAspectFill
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

        let photo = self.photoViewModel.photos[indexPath.row]
        (cell as! PhotoCell).imageView.image = UIImage(named: "dummyImage")

        ImageDownloadManager.shared.downloadImage(photo, indexPath: indexPath) { (image, imageIndexPath, error) in
            if let indexPathNew = imageIndexPath, indexPathNew == indexPath {
                DispatchQueue.main.async {
                    (cell as! PhotoCell).imageView.image = image
                }
            }
        }
    }

}

请找到图片下载器类:

typealias ImageDownloadHandler = (_ image: UIImage?, _ indexPath: IndexPath?, _ error: Error?) -> Void

final class ImageDownloadManager {

    private var completionHandler: ImageDownloadHandler?
    lazy var imageDownloadQueue: OperationQueue = {
        var queue = OperationQueue()
        queue.name = "imageDownloadQueue"
        queue.qualityOfService = .userInteractive
        return queue
    }()

    let imageCache = NSCache<NSString, UIImage>()
    static let shared = ImageDownloadManager()
    private init () {}

    func downloadImage(_ photo: Photos, indexPath: IndexPath?, handler: @escaping ImageDownloadHandler) {
        self.completionHandler = handler
        guard let url = photo.getImageURL() else {
            return
        }
        if let cachedImage = imageCache.object(forKey: photo.id as NSString) {
            self.completionHandler?(cachedImage, indexPath, nil)
        } else {
                let operation = CustomOperation(url: url, indexPath: indexPath)
                if indexPath == nil {
                }
            operation.queuePriority = .high
                operation.downloadHandler = { (image, indexPath, error) in
                    if let newImage = image {
                        self.imageCache.setObject(newImage, forKey: photo.id as NSString)
                    }
                    self.completionHandler?(image, indexPath, error)
                }
                imageDownloadQueue.addOperation(operation)
        }
    }

    func cancelAll() {
        imageDownloadQueue.cancelAllOperations()
    }


}

最佳答案

下载图像后,在主线程上执行指令 (cell as! PhotoCell).imageView.image = image。但这不会重新显示您的 collectionView 单元格。
此外,通常不会调用 collectionView:willDisplayCell:forItemAtIndexPath:docs

The collection view calls this method before adding a cell to its content.

然而,当您在单元格中滚动时,即当它变得可见时,它会被调用。这就是为什么在单元格滚动后显示图像的原因。

所以我的建议是:

  • 下载图像后,更新您的 collectionView 数据源 以便 collectionView:cellForItemAtIndexPath: 可以配置单元格 与图像。
  • 调用 reloadItems(at:) 使用一个仅包含更新单元格索引路径的数组。

关于ios - 异步下载图像时, Collection View 单元格中的图像不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57970876/

相关文章:

ios CocoaPods 无法自动选择 Xcode 项目。像这样在你的 Podfile 中指定一个

ios - 如何在设备上的每个触摸位置周围绘制一个圆圈?

ios - 当我 popToRootViewControllerAnimated 时导航栏消失

ios - UIView 使用自动布局拥抱所有 subview

ios - 如何更改 NSMutableAttributedString 的默认字体和字体大小

swift - 表格 ScrollView 下的文本 swift

swift - Swift 中插值字符串中的数字是否受语言环境影响?

ios - UITableViewCell contentView 具有 autoResizingMask 约束 'UIView-Encapsulated-Layout-Height' 与自动调整大小的自动布局冲突

ios - 点击发送或取消按钮后如何关闭邮件 View Controller

ios - UIButton 按下时不会更改文本颜色