У меня есть UICollectionView
, который показывает фотографии из библиотеки фотографий пользователя. Я разрешаю пользователю выбрать несколько фотографий, и после некоторой обработки я сохраняю измененные фотографии как новые фотографии в библиотеку фотографий (не удаляя старые). Я использую этот метод для сохранения фотографий:
fileprivate func saveImagesToLibrary(imageArray:[UIImage]){
var savedImageNum = 0
let increment = 0.8 / Float(imageArray.count)
var percentage:Float = 0.2
self.getAlbumWithName(name: albumNameToCreate) { (assetCollection) in
if let collection = assetCollection {
let group = DispatchGroup()
for (_,image) in imageArray.enumerated(){
group.enter()
PHPhotoLibrary.shared().performChanges({
let request = PHAssetChangeRequest.creationRequestForAsset(from: image)
let placeholder = request.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: collection)
if let placeholder = placeholder, let albumChangeRequest = albumChangeRequest {
albumChangeRequest.addAssets([placeholder] as NSArray)
}
}, completionHandler: { (success, error) in
DispatchQueue.main.async {
percentage = percentage+increment
SVProgressHUD.showProgress(Float(percentage), status: "Saving photos...")
}
group.leave()
if success == true {
savedImageNum += 1
} else {
if let inError = error {
print(inError)
}
}
})
}
group.notify(queue: .main, execute: {
var status = ""
if savedImageNum == 0 {
self.dismissProgressHUDWithError()
} else if savedImageNum == 1 {
status = "Saved \(savedImageNum) image out of \(self.selectedAssets.count) in \"Saved from Xif\" album"
SVProgressHUD.showSuccess(withStatus: status)
SVProgressHUD.dismiss(withDelay: 3)
self.view.isUserInteractionEnabled = true
self.removeAllSelections()
self.dismissDimmerView()
} else {
status = "Saved \(savedImageNum) images out of \(self.selectedAssets.count) in \"Saved from Xif\" album"
SVProgressHUD.showSuccess(withStatus: status)
SVProgressHUD.dismiss(withDelay: 3)
self.view.isUserInteractionEnabled = true
self.removeAllSelections()
self.dismissDimmerView()
}
})
} else {
DispatchQueue.main.async {
self.dismissProgressHUDWithError()
}
}
}
}
Как вы можете видеть выше, я использую removeAllSelections (), чтобы отменить выбор всех ячеек:
fileprivate func removeAllSelections(){
selectedAssets = []
disableDeleteButton()
photoCollectionView.reloadData()
}
Я использую removeAllSelections () и в других местах моего кода, и все работает нормально, однако, когда я использую его в своем методе saveImagesToLibrary, иногда не удается удалить выборки. Кажется, что команда reloadDeta () не работает должным образом, потому что она конфликтует с вызовом PHPhotoLibraryChangeObserver, который также пытается обновить представление коллекции:
extension centerViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let changes = changeInstance.changeDetails(for: inFetchResult)
else { return }
// Change notifications may originate from a background queue.
// As such, re-dispatch execution to the main queue before acting
// on the change, so you can update the UI.
DispatchQueue.main.sync {
// Hang on to the new fetch result.
inFetchResult = changes.fetchResultAfterChanges
updateSelectedAssetsAfterChange()
// If we have incremental changes, animate them in the collection view.
if changes.hasIncrementalChanges {
guard let collectionView = self.photoCollectionView else { fatalError() }
// Handle removals, insertions, and moves in a batch update.
collectionView.performBatchUpdates({
if let removed = changes.removedIndexes, !removed.isEmpty {
collectionView.deleteItems(at: removed.map({ IndexPath(item: $0, section: 0) }))
}
if let inserted = changes.insertedIndexes, !inserted.isEmpty {
collectionView.insertItems(at: inserted.map({ IndexPath(item: $0, section: 0) }))
}
changes.enumerateMoves { fromIndex, toIndex in
collectionView.moveItem(at: IndexPath(item: fromIndex, section: 0),
to: IndexPath(item: toIndex, section: 0))
}
})
// We are reloading items after the batch update since `PHFetchResultChangeDetails.changedIndexes` refers to
// items in the *after* state and not the *before* state as expected by `performBatchUpdates(_:completion:)`.
if let changed = changes.changedIndexes, !changed.isEmpty {
collectionView.reloadItems(at: changed.map({ IndexPath(item: $0, section: 0) }))
}
} else {
// Reload the collection view if incremental changes are not available.
photoCollectionView.reloadData()
}
resetCachedAssets()
updateFooter()
}
}
}
Я пытался поместить removeAllSelections () в photoLibraryDidChange (), но это не решает проблему, так как photoLibraryDidChange () вызывается несколько раз, и нет способа узнать, когда он полностью завершает все свои задачи. Любая помощь приветствуется.