#ios #swift #uicollectionview #photokit
#iOS #swift #uicollectionview #фотокит #photokit
Вопрос:
Я создаю функцию множественного выбора для своего представления коллекции, в котором отображаются фотографии из библиотеки пользователя. Я отслеживаю выбранные indexPaths в массиве и хочу обновить их на случай, если событие наблюдателя за изменением библиотеки фотографий произойдет в середине выбора ячеек. например, если пользователь выбрал индексы 3 и 4, а событие change observer удаляет индексы 1 и 2 из представления коллекции, выбранные индексы должны измениться на 1 и 2.
Я пытаюсь сделать это вручную, используя эти функции:
fileprivate func removeIndicesFromSelections(indicesToRemove:IndexSet){
var itemToRemove: Int?
for (_, removeableIndex) in indicesToRemove.map({$0}).enumerated() {
itemToRemove = nil
for (itemIndex,indexPath) in selectedIndices.enumerated() {
//deduct 1 from indices after the deletion index
if (indexPath.item > removeableIndex) amp;amp; (indexPath.item > 0) {
selectedIndices[itemIndex] = IndexPath(item: indexPath.item - 1, section: 0)
} else if indexPath.item == removeableIndex {
itemToRemove = itemIndex
}
}
if let remove = itemToRemove {
selectedIndices.remove(at: remove)
disableDeleteButtonIfNeeded()
}
}
}
fileprivate func moveSelectedIndicesAfterInsertion (insertedIndices:IndexSet){
for (_, insertedIndex) in insertedIndices.map({$0}).enumerated() {
for (itemIndex,indexPath) in selectedIndices.enumerated() {
//add 1 to indices after the insertion index
if (indexPath.item >= insertedIndex) {
selectedIndices[itemIndex] = IndexPath(item: indexPath.item 1, section: 0)
}
}
}
}
Однако это становится сложнее, чем я ожидал, и я продолжаю находить в них ошибки. Есть ли лучший способ справиться с этой ситуацией (например, любые встроенные возможности просмотра коллекции), или мне просто нужно придумать свои собственные функции, как указано выше?
Ответ №1:
Вы на правильном пути, но вы должны хранить ссылку на то, какой объект пользователь фактически выбрал, а не на то, где он его выбрал (поскольку это может измениться).
В этом случае вы должны сохранить ссылку на идентификаторы выбранных фотографий (см. Документы), а затем вы можете определить, какая ячейка / путь к индексу должна быть выбрана. Вы можете сравнить свой массив выбора с источником данных изображения, чтобы определить, какой путь к индексу является наиболее актуальным.
Ответ №2:
Существует решение, предоставленное Apple. Вы можете найти более подробную информацию на официальной странице документации:
Обычно вы хотите принять PHPhotoLibraryChangeObserver
и реализовать следующую функцию:
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let collectionView = self.collectionView else { return }
// Change notifications may be made on a background queue.
// Re-dispatch to the main queue to update the UI.
DispatchQueue.main.sync {
// Check for changes to the displayed album itself
// (its existence and metadata, not its member assets).
if let albumChanges = changeInstance.changeDetails(for: assetCollection) {
// Fetch the new album and update the UI accordingly.
assetCollection = albumChanges.objectAfterChanges! as! PHAssetCollection
navigationController?.navigationItem.title = assetCollection.localizedTitle
}
// Check for changes to the list of assets (insertions, deletions, moves, or updates).
if let changes = changeInstance.changeDetails(for: fetchResult) {
// Keep the new fetch result for future use.
fetchResult = changes.fetchResultAfterChanges
if changes.hasIncrementalChanges {
// If there are incremental diffs, animate them in the collection view.
collectionView.performBatchUpdates({
// For indexes to make sense, updates must be in this order:
// delete, insert, reload, move
if let removed = changes.removedIndexes where removed.count > 0 {
collectionView.deleteItems(at: removed.map { IndexPath(item: $0, section:0) })
}
if let inserted = changes.insertedIndexes where inserted.count > 0 {
collectionView.insertItems(at: inserted.map { IndexPath(item: $0, section:0) })
}
if let changed = changes.changedIndexes where changed.count > 0 {
collectionView.reloadItems(at: changed.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))
}
})
} else {
// Reload the collection view if incremental diffs are not available.
collectionView.reloadData()
}
}
}
}