如何从PHAsset获取视频缩略图并填充至UICollectionView?
嘿,这个问题我太熟悉了!其实给UICollectionView添加视频缩略图和加载图片的逻辑是相通的,核心都是用PHImageManager来处理PHAsset资源,只是针对视频需要做一点点参数调整。我给你详细拆解下步骤:
核心方案:用PHImageManager获取视频缩略图
不管是图片还是视频,PHImageManager都能帮你获取对应的可视化内容——视频的话,它会默认提取视频的第一帧作为缩略图,完全满足你的需求。
1. 配置视频缩略图的请求参数
首先你需要创建一个PHImageRequestOptions实例,设置合适的参数来保证缩略图的加载效率和质量:
let videoRequestOptions = PHImageRequestOptions() videoRequestOptions.isSynchronous = false // 异步请求,避免阻塞主线程 videoRequestOptions.deliveryMode = .highQualityFormat // 优先高质量缩略图,追求速度的话可以改成.fastFormat videoRequestOptions.resizeMode = .aspectFill // 保持宽高比填充目标尺寸,避免拉伸 videoRequestOptions.isNetworkAccessAllowed = true // 如果视频存在iCloud上,允许联网获取
2. 在UICollectionView数据源方法中处理视频
在collectionView(_:cellForItemAt:)方法里,判断当前PHAsset的类型,分别处理图片和视频:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // 假设你的自定义cell有一个UIImageView用来显示缩略图,还有一个播放图标用来区分视频 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MediaCell", for: indexPath) as! MediaCell let asset = images[indexPath.item] // 先清空cell的旧内容,避免复用错乱 cell.mediaImageView.image = nil cell.playIconImageView.isHidden = true if asset.mediaType == .image { // 你的图片加载逻辑(和你之前的代码一致) let imageOptions = PHImageRequestOptions() imageOptions.resizeMode = .aspectFill PHImageManager.default().requestImage(for: asset, targetSize: cell.mediaImageView.bounds.size, contentMode: .aspectFill, options: imageOptions) { image, _ in cell.mediaImageView.image = image } } else if asset.mediaType == .video { // 请求视频缩略图 cell.playIconImageView.isHidden = false // 显示播放图标,区分视频 let requestID = PHImageManager.default().requestImage(for: asset, targetSize: cell.mediaImageView.bounds.size, contentMode: .aspectFill, options: videoRequestOptions) { image, _ in cell.mediaImageView.image = image } // 保存请求ID,复用cell时可以取消未完成的请求 cell.imageRequestID = requestID } return cell }
3. 优化:避免复用错乱和内存浪费
为了防止cell复用的时候出现图片/缩略图错乱的问题,建议在自定义cell里添加一个属性存储请求ID,复用前取消未完成的请求:
// 自定义MediaCell的代码 class MediaCell: UICollectionViewCell { @IBOutlet weak var mediaImageView: UIImageView! @IBOutlet weak var playIconImageView: UIImageView! // 存储图片/视频请求的ID var imageRequestID: PHImageRequestID? override func prepareForReuse() { super.prepareForReuse() // 取消未完成的请求 if let requestID = imageRequestID { PHImageManager.default().cancelImageRequest(requestID) } imageRequestID = nil } }
额外小技巧:自定义视频缩略图帧
如果你不想用默认的第一帧,而是想获取视频的某个特定帧,可以结合AVAsset来实现,但PHImageManager的方案已经能覆盖绝大多数场景,而且它会自动处理缓存和iCloud资源的加载,更省心。
内容的提问来源于stack exchange,提问作者itsfaraaz
相关产品推荐
相关产品推荐

