I'm using third party library called BSImagePicker to select multiple images from the photo library. I can set maximum PHAssets
to be selected, but the problem comes when I display the BSImagePickerController
to choose more photos. Those PHAssets
are just additionally added to the selectedAssets
and practically duplicates the images. I tried to remove the duplicates PHAsset
and images using but it's not working:
extension Array where Element: Equatable {
mutating func removeDuplicates() {
var result = [Element]()
for value in self {
if !result.contains(value) {
result.append(value)
}
}
self = result
}
}
func presentBSImagePickerController(vc: BSImagePickerViewController) {
self.bs_presentImagePickerController(vc, animated: true,
select: { (asset: PHAsset) -> Void in
}, deselect: { (asset: PHAsset) -> Void in
// User deselected an assets.
}, cancel: { (assets: [PHAsset]) -> Void in
// User cancelled. And this where the assets currently selected.
}, finish: { (assets: [PHAsset]) -> Void in
// User finished with these assets
for i in 0..<assets.count {
self.selectedAssets.append(assets[i])
}
self.selectedAssets.removeDuplicates()
self.convertAssetToImages()
}, completion: nil)
}
func convertAssetToImages() -> Void {
if selectedAssets.count != 0 {
for i in 0..<selectedAssets.count {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: selectedAssets[i], targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: option, resultHandler: {(result, info)->Void in
thumbnail = result!
})
let data = UIImageJPEGRepresentation(thumbnail, 0.7)
let newImage = UIImage(data: data!)
self.photosArray.append(newImage! as UIImage)
self.photosArray.removeDuplicates()
print(self.photosArray.removeDuplicates())
DispatchQueue.main.async {
self.collectionView.reloadData() // reloads the collection view on main thread
}
}
}
}
The problem with
for i in 0..<assets.count {
self.selectedAssets.append(assets[i])
}
self.selectedAssets.removeDuplicates()
...is that your removeDuplicates
(apart from being intolerably slow!) simply assumes that PHAsset equality is the mark of a duplicated image. It isn't. An asset is just a temporary representative of what's in the library. What you want to know is whether the local identifier of an asset matches that of one that you already have. I would suggest this:
var ids = Set(self.selectedAssets.map {$0.localIdentifier})
for asset in assets {
if !ids.contains(asset.localIdentifier) {
ids.insert(asset.localIdentifier)
self.selectedAssets.append(asset)
}
}
We make a list of all the local identifiers of the assets we already have. Then we append an asset (and its identifier) only if its identifier is not in the list. This will be much faster (because Set contains
is much faster than Array contains
), and should also prevent "the same photo" from appearing twice.