【发布时间】:2020-01-21 13:36:27
【问题描述】:
我正在使用UICollectionViewDiffableDataSource 和NSFetchedResultsController 在我的UIViewController 中填充我的UICollectionView。
为了添加对单元格重新排序的功能,我添加了一个 UILongPressGestureRecognizer 并将 UICollectionViewDiffableDataSource 子类化,以便使用它的 canMoveItemAt: 和 moveItemAt: 方法。
重新排序单元格时会发生以下情况:
-
moveItemAt:被调用,我更新对象位置属性并保存 MOC -
NSFetchedResultsControllerDelegate的controllerDidChangeContent:被调用,我从当前 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)
}
}
【问题讨论】:
-
你找到解决方法了吗?
标签: ios swift uicollectionview nsfetchedresultscontroller ios13