如何提高获取照片缩略图的效率并在Swift中的UICollectionView中显示它们

时间:2018-04-22 21:57:40

标签: ios swift uicollectionview thumbnails

我正在Swift中编写一个简单的自定义照片选择器。看看GIF,你会发现它有什么问题:

enter image description here

当我点击状态栏到quickly滚动到顶部时,图片全部混淆,因为正在重复使用单元格并且重新生成缩略图需要很短的时间,因此,会发生这种情况。我想知道无论我滚动多快,我怎么能解决这个问题?我的这个选择器的代码是:

func getThumbnail(asset: PHAsset, targetSize: CGSize, onComplete: @escaping (UIImage?, [AnyHashable: Any]?) -> ()) {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.resizeMode = .fast
    option.isNetworkAccessAllowed = true

    manager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: option) { (thumbnail, info) in
        onComplete(thumbnail, info)
    }
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = ...

    let asset = photos[indexPath.row]    // "photos" is an array of all photos in library
                                         // and its type is "[PHAsset]"

    let photoSize = collectionView.frame.width / 3
    getThumbnail(asset: asset, targetSize: CGSize(width: photoSize, height: photoSize, onComplete: { (image, _) -> Void in
        (cell.viewWithTag(1) as! UIImageView).image = image
        // A cell has a UIImageView, whose size is equal to cell size,
        // whose tag = 1
    }))

    return cell
}

3 个答案:

答案 0 :(得分:0)

在你的cellForItemAt第一行放

cell.imageView.image = nil

这样可以防止出列的单元重复使用可以减少闪烁的图像。如果图像在内存中,它会立即被替换,没有问题。

仅仅因为您使用缓存并不意味着您的所有图像当前都在内存中。当您将图像读取到内存时会发生闪烁,尤其是在网络上以及需要调整单元格大小时(尽管看起来大小相同)。

您可能只想考虑在滚动结束时更新视图ONCE,而不是每个单元格。

您可以检查scrollViewWillBeginDragging以关闭更新,并在需要时检查scrollViewDidEndDecelerating以进行更新。

答案 1 :(得分:0)

我在UITableView中遇到了同样的问题。当我使用AlamofireImage时

af_setImage(withURL:  URL(string: pictureUrl))

然后我使用AlamofireImage&#39>

af_setImage(withURL:  URL(string: pictureUrl)!, placeholderImage: UIImage(named: "YourPlaceholder.png")) 

使用占位符图片解决问题。

答案 2 :(得分:0)

从你的代码:

let cell = ...

此时,您还没有图像,因此您应该将图像视图的图像设置为nil或占位符图像:

let cell = ...
(cell.viewWithTag(1) as! UIImageView).image = placeholderImage

同样来自您的代码:

getThumbnail(asset: asset, targetSize: CGSize(width: photoSize, height: photoSize, onComplete: { (image, _) -> Void in
    (cell.viewWithTag(1) as! UIImageView).image = image

此时,cell可能不再是原始索引路径(因此对于image)的正确单元格。原始索引路径可能没有单元格,或者索引路径可能有不同的单元格。您需要向集合视图询问正确的单元格:

getThumbnail(asset: asset, targetSize: CGSize(width: photoSize, height: photoSize, onComplete: { (image, _) -> Void in
    guard let cell = collectionView.cellForItem(at: indexPath) else { return }
    (cell.viewWithTag(1) as! UIImageView).image = image