使用PHAsset获取图片时避免重复

时间:2022-09-05 21:53:39

On iOS 8, I want to get all pictures stored on the device. My problem is that I do get them, but some are present more than once. The PHAsset properties (hidden, mediaSubtypes, etc.) are the same for all pictures, so I can't for example rule out the PHAssetMediaSubtypePhotoHDR subtypes. The only way I found is not adding multiple pictures with the same date, but this is a problem when multiple photos were saved with the same creation date.

在iOS 8上,我希望将所有图片存储在设备上。我的问题是我确实得到了它们,但有些不止一次。 PHAsset属性(隐藏,mediaSubtypes等)对于所有图片都是相同的,因此我不能排除PHAssetMediaSubtypePhotoHDR子类型。我找到的唯一方法是不添加具有相同日期的多张图片,但是当使用相同的创建日期保存多张照片时,这是一个问题。

Does anybody know why I get these duplicates and what I can do to avoid them?

有谁知道我为什么会得到这些副本以及我能做些什么来避免它们?

This is how I get the pictures:

这是我得到图片的方式:

    PHFetchOptions *fetchOptions = [PHFetchOptions new];
    fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES],];
    PHFetchResult *phAssets = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];

5 个解决方案

#1


5  

You can try to use Moments Collections:

您可以尝试使用Moments Collections:

PHFetchResult * moments = [PHAssetCollection fetchMomentsWithOptions:nil];            
for (PHAssetCollection * moment in moments) {
    PHFetchResult * assetsFetchResults = [PHAsset fetchAssetsInAssetCollection:moment options:nil];
    for (PHAsset * asset in assetsFetchResults) {
        //Do something with asset, for example add them to array
    }
}

#2


6  

Since iOS 8.1, the behavior of the fetchAssetsWithMediaType: and fetchAssetsWithOptions: methods has changed, and they no longer include photos synchronized to the device from iTunes or photos stored in an iCloud Shared Photo Stream.

自iOS 8.1起,fetchAssetsWithMediaType:和fetchAssetsWithOptions:方法的行为已经改变,它们不再包括从iTunes同步到设备的照片或存储在iCloud共享照片流中的照片。

Source: Document Revision History and PHAsset Class Reference.

来源:文档修订历史和PHAsset类参考。

#3


3  

I had the same problem, and for me, the duplicates were images that were in the my photostream album. To work around the issue, i now use the FetchMoments method from the PHAssetCollection class, and then I fetch all assets for each moment in the fetch result. This way i get all images without getting repeated images.

我有同样的问题,对我来说,重复是我的照片流专辑中的图像。为了解决这个问题,我现在使用PHAssetCollection类中的FetchMoments方法,然后在获取结果中的每个时刻获取所有资产。这样我就可以获得所有图像而无需重复图像。

If someone finds a better solution, please let me know.

如果有人找到更好的解决方案,请告诉我。

#4


0  

On a flyer, are these assets are part of a burst? (cf. PHAsset.burstIdentifier, etc.) If so, you can adjust accordingly.

在传单上,这些资产是爆发的一部分吗? (参见PHAsset.burstIdentifier等)如果是这样,您可以相应地进行调整。

#5


0  

you can use the "PHImageRequestOptions" to setup only high quality images for example!

您可以使用“PHImageRequestOptions”来设置高质量的图像,例如!

//Setting up the deliveryMode in PHImageRequestOptions()
fileprivate func imageRequestOptions() -> PHImageRequestOptions {
    let requestOption = PHImageRequestOptions()
    requestOption.deliveryMode = .highQualityFormat
    return requestOption
}

fileprivate func fetchImages(){

    let fetchOptions = assetsFetchOptions() //get fetchOptions only. Don`t worry
    let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)

    allPhotos.enumerateObjects({ (asset, index, stop) in
        print(asset)

        let imageManager = PHImageManager.default()
        let targetSize = CGSize(width: 200, height: 200)

        //This function uses the "imageRequestOptions()" function to set up the "options:" field in this .requestImage() function.
        imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFit, options: self.imageRequestOptions(), resultHandler: { (image, info) in

            if let image = image {
                self.images.append(image)
                self.assets.append(asset)

                if self.selectedImage == nil {
                    self.selectedImage = image
                }
            }

            if index == allPhotos.count - 1 {
                self.collectionView?.reloadData()
            }
        })
    })
}

#1


5  

You can try to use Moments Collections:

您可以尝试使用Moments Collections:

PHFetchResult * moments = [PHAssetCollection fetchMomentsWithOptions:nil];            
for (PHAssetCollection * moment in moments) {
    PHFetchResult * assetsFetchResults = [PHAsset fetchAssetsInAssetCollection:moment options:nil];
    for (PHAsset * asset in assetsFetchResults) {
        //Do something with asset, for example add them to array
    }
}

#2


6  

Since iOS 8.1, the behavior of the fetchAssetsWithMediaType: and fetchAssetsWithOptions: methods has changed, and they no longer include photos synchronized to the device from iTunes or photos stored in an iCloud Shared Photo Stream.

自iOS 8.1起,fetchAssetsWithMediaType:和fetchAssetsWithOptions:方法的行为已经改变,它们不再包括从iTunes同步到设备的照片或存储在iCloud共享照片流中的照片。

Source: Document Revision History and PHAsset Class Reference.

来源:文档修订历史和PHAsset类参考。

#3


3  

I had the same problem, and for me, the duplicates were images that were in the my photostream album. To work around the issue, i now use the FetchMoments method from the PHAssetCollection class, and then I fetch all assets for each moment in the fetch result. This way i get all images without getting repeated images.

我有同样的问题,对我来说,重复是我的照片流专辑中的图像。为了解决这个问题,我现在使用PHAssetCollection类中的FetchMoments方法,然后在获取结果中的每个时刻获取所有资产。这样我就可以获得所有图像而无需重复图像。

If someone finds a better solution, please let me know.

如果有人找到更好的解决方案,请告诉我。

#4


0  

On a flyer, are these assets are part of a burst? (cf. PHAsset.burstIdentifier, etc.) If so, you can adjust accordingly.

在传单上,这些资产是爆发的一部分吗? (参见PHAsset.burstIdentifier等)如果是这样,您可以相应地进行调整。

#5


0  

you can use the "PHImageRequestOptions" to setup only high quality images for example!

您可以使用“PHImageRequestOptions”来设置高质量的图像,例如!

//Setting up the deliveryMode in PHImageRequestOptions()
fileprivate func imageRequestOptions() -> PHImageRequestOptions {
    let requestOption = PHImageRequestOptions()
    requestOption.deliveryMode = .highQualityFormat
    return requestOption
}

fileprivate func fetchImages(){

    let fetchOptions = assetsFetchOptions() //get fetchOptions only. Don`t worry
    let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)

    allPhotos.enumerateObjects({ (asset, index, stop) in
        print(asset)

        let imageManager = PHImageManager.default()
        let targetSize = CGSize(width: 200, height: 200)

        //This function uses the "imageRequestOptions()" function to set up the "options:" field in this .requestImage() function.
        imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFit, options: self.imageRequestOptions(), resultHandler: { (image, info) in

            if let image = image {
                self.images.append(image)
                self.assets.append(asset)

                if self.selectedImage == nil {
                    self.selectedImage = image
                }
            }

            if index == allPhotos.count - 1 {
                self.collectionView?.reloadData()
            }
        })
    })
}