Обновление выбранных индексов collectionview после ответа на событие PHPhotoLibraryChangeObserver

#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()
            }
        }
    }
}