PHCachingImageManager.requestImage 总是被调用两次?

Posted

技术标签:

【中文标题】PHCachingImageManager.requestImage 总是被调用两次?【英文标题】:PHCachingImageManager.requestImage is always called twice? 【发布时间】:2017-09-20 14:23:04 【问题描述】:

我有一个带有自定义UICollectionViewCellUICollectionView,它应该从单元格中的每个UIImageView 中的照片(通常用户可以选择多于一张照片)中获取并显示缩略图(低质量)照片。

我一直在玩PHImageRequestOptions 及其属性,阅读它们。我什至将nil 作为requestImage(for: PHAsset) 方法的参数传递,因为我不确定我错在哪里。

问题是requestImage(for: PHAsset) 方法被调用了两次。我需要第一次调用它以在每个集合视图单元格中以低质量(缩略图图像)设置图像,一旦完整尺寸的图像准备好,它应该被添加到一个名为assetsTurnedIntoImages 的图像数组中。问题是我做错了,我总是得到ifelse 方法调用两次,所以基本上,如果我从相机胶卷中选择了 4 张图像(因此,我在assets 数组),当他们通过 requestImage(for:asset) 方法时,我在assetsTurnedIntoImages 中得到 8 个图像而不是 4 个。所以这是我的代码

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    
        print("Assets count is:", assets.count)
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoPostCVCell", for: indexPath) as! PhotoPostCVCell
        if let takenImage = cameraPhotoUIImage
        
            cell.cellImage.image = takenImage
        
        if assets.count > 0
        
            let asset = assets[indexPath.row]

//            var imageRequestOptions: PHImageRequestOptions
//            
//                let options = PHImageRequestOptions()
//                //options.version = .current
//                //options.resizeMode = .exact
//                //options.deliveryMode = .fastFormat
//                options.isSynchronous = true
//                return options
//            
            let targetSize = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
            imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: nil)
             (image, info) in
                if image != nil
                
                    let imageQualityState = info![PHImageResultIsDegradedKey] as! Bool

                    if imageQualityState
                    
                        print("LOW QUALITY")
                        print("Image Quality State is:", imageQualityState)
                        cell.cellImage.image = image
                        print(image!.size)
                    
                    else
                    
                        print(image!.size)
                        cell.cellImage.image = image
                        self.assetsTurnedIntoImages.append(image!)
                    
                
            
        
        return cell
    

【问题讨论】:

【参考方案1】:

您可以通过包含以下条件来丢弃那些低分辨率副本:

imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: nil)  (image, info) in

let isDegraded = (info?[PHImageResultIsDegradedKey] as? Bool) ?? false
if isDegraded 
   return

【讨论】:

【参考方案2】:

担心requestImage:forAsset 被调用两次,您无能为力。但是,您可以更改将图像放入数组的方式以避免重复。我可以建议:

self.assetsTurnedIntoImages[indexPath.row] = image

这将导致第二次传入完成的图像替换第一次调用的图像,避免重复。

您需要提前为您的数组预初始化足够的空间,以便indexPath.row 不会尝试越界访问您的数组。 在ViewDidLoad 中添加以下内容:

self.assetsTurnedIntoImages = [UIImage](repeating: UIImage(), count: assets.count)

【讨论】:

我遇到了崩溃。我收到一个错误fatal error: Array index is out of range 嗯,他们不能按顺序被调用,假设 requestImage 在图像 3 被调用之前在图像 1 被调用。我会更新我的答案。 我按照你的建议做了,但是assetsTurnedIntoImages 现在的图片数量是原来的三倍。如果我从照片中选择了 4 个评估,我会在数组中得到 12 个图像。 您有 12 个资产吗? ViewDidLoad 中的 assets.count 是什么? 不,是 4。这就是它如此令人困惑的原因。我不明白为什么它们现在增加了两倍。

以上是关于PHCachingImageManager.requestImage 总是被调用两次?的主要内容,如果未能解决你的问题,请参考以下文章