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.
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];
You can try to use 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
}
}
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.
Source: Document Revision History and PHAsset Class Reference.
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.
If someone finds a better solution, please let me know.
On a flyer, are these assets are part of a burst? (cf. PHAsset.burstIdentifier
, etc.) If so, you can adjust accordingly.
you can use the "PHImageRequestOptions" to setup only high quality images for example!
//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()
}
})
})
}