Swift中CollectionView视频缩略图重复显示问题求助
解决CollectionView视频缩略图重复显示问题
问题根源
UICollectionView的Cell复用机制导致:当异步加载缩略图的请求完成时,Cell可能已经被复用给其他列表项,此时错误地将旧请求的图片设置到新的列表项上,造成重复显示。滚动后Cell重新加载对应请求,显示恢复正常。
修复方案
1. 为Cell添加请求校验,避免复用后错误赋值
修改TemplateCell代码,增加当前视频URL的校验逻辑,确保只有当前Cell绑定的请求完成后才设置图片:
class TemplateCell: UICollectionViewCell { @IBOutlet weak var thumbnailImageView: UIImageView! // 记录当前Cell绑定的视频URL,用于请求校验 private var currentVideoURL: URL? func configure(with videoURL: URL) { self.currentVideoURL = videoURL // 复用前清空旧图片,避免残留显示 self.thumbnailImageView.image = nil } func loadVideo() { guard let videoURL = self.currentVideoURL else { return } VideoThumbnailManager.shared.generateThumbnailImage(for: videoURL) { [weak self] thumbnail in DispatchQueue.main.async { // 仅当当前Cell的URL与请求URL匹配时,才设置图片 guard let self = self, self.currentVideoURL == videoURL else { return } self.thumbnailImageView.image = thumbnail } } } func unloadVideo() { // 回收Cell时清空所有状态 self.currentVideoURL = nil self.thumbnailImageView.image = nil self.videoPlayerLayer?.removeFromSuperlayer() } }
2. 优化VideoThumbnailManager,利用SDWebImage原生能力(推荐)
SDWebImage本身支持视频缩略图的加载与缓存,无需手动实现AVAsset逻辑,自带请求取消、缓存管理功能,稳定性更高:
import SDWebImage import SDWebImageVideoCoder // 需要引入该扩展库 class VideoThumbnailManager { static let shared = VideoThumbnailManager() private let imageManager: SDWebImageManager private init() { // 配置支持视频缩略图解码 let config = SDWebImageConfiguration.default config.imageCodersManager.addCoder(SDWebImageVideoCoder.shared) self.imageManager = SDWebImageManager(configuration: config) } func generateThumbnailImage(for videoURL: URL, completion: @escaping (UIImage?) -> Void) { let options: SDWebImageOptions = [ .scaleDownLargeImages, .continueInBackground, .refreshCached // 可选:需要时触发缓存刷新 ] // SDWebImage自动处理缓存、请求及视频缩略图生成 imageManager.loadImage(with: videoURL, options: options) { image, _, _, _, _, _ in completion(image) } } }
3. 完善CollectionView复用回调逻辑
确保didEndDisplaying中完全清空Cell状态,避免残留数据影响下一次复用:
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { guard let videoCell = cell as? TemplateCell else { return } videoCell.unloadVideo() }
额外注意事项
- 若使用优化后的
VideoThumbnailManager,需确保项目已引入SDWebImageVideoCoder库(可通过CocoaPods或Swift Package Manager添加) - 若坚持自定义AVAsset生成缩略图,需在Cell的
unloadVideo方法中调用imageGenerator.cancelAllCGImageGeneration(),取消未完成的请求,避免资源浪费
内容的提问来源于stack exchange,提问作者Erhan Demirci
相关产品推荐
相关产品推荐

