Я использую UICollectionViewDiffableDataSource и NSFetchedResultsController
для заполнения моего UICollectionView
внутри моего UIViewController
.
Чтобы добавить возможность переупорядочения ячеек, я добавил UILongPressGestureRecognizer
и подклассы UICollectionViewDiffableDataSource
, чтобы использовать методы canMoveItemAt:
и moveItemAt:
.
При переупорядочении ячейки следующеепроисходят вещи:
moveItemAt:
вызывается, и я обновляю свойство позиции объектов и сохраняю MOC controllerDidChangeContent:
из NSFetchedResultsControllerDelegate
вызывается, и я создаю новый снимокот текущего fetchedObjects и применить его.
Когда я применяю dataSource?.apply(snapshot, animatingDifferences: true)
, ячейки немедленно переключаются назад.Если я установлю animatingDifferences: false
, это будет работать, но все ячейки будут перезагружены заметно .
Есть ли здесь наилучшая практика, как осуществить переупорядочение ячеек на UICollectionViewDiffableDataSource
и NSFetchedResultsController
?
Вот мои упомянутые методы:
// ViewController
func createSnapshot(animated: Bool = true) {
var snapshot = NSDiffableDataSourceSnapshot<Int, Favorite>()
snapshot.appendSections([0])
snapshot.appendItems(provider.fetchedResultsController.fetchedObjects ?? [])
dataSource?.apply(snapshot, animatingDifferences: animated)
}
// NSFetchedResultsControllerDelegate
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
createSnapshot(animated: false)
}
// Subclassed UICollectionViewDiffableDataSource
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
provider.moveFavorite(from: sourceIndexPath.row, to: destinationIndexPath.row)
}
// Actual cell moving in a provider class
public func moveFavorite(from source: Int, to destination: Int) {
guard let favorites = fetchedResultsController.fetchedObjects else { return }
if source < destination {
let partialObjects = favorites.filter({ $0.position <= destination && $0.position >= source })
for object in partialObjects {
object.position -= 1
}
let movedFavorite = partialObjects.first
movedFavorite?.position = Int64(destination)
}
else {
let partialObjects = favorites.filter({ $0.position >= destination && $0.position <= source })
for object in partialObjects {
object.position += 1
}
let movedFavorite = partialObjects.last
movedFavorite?.position = Int64(destination)
}
do {
try coreDataHandler.mainContext.save()
} catch let error as NSError {
print(error.localizedDescription)
}
}