![](/img/trans.png)
[英]Attempting to reordering UITableView using an NSFetchedResultsController
[英]Reordering Cells with UICollectionViewDiffableDataSource and NSFetchedResultsController
我正在使用UICollectionViewDiffableDataSource和UICollectionView
在NSFetchedResultsController
中填充我的UIViewController
。
为了添加重新排序单元格的功能,我添加了一个UILongPressGestureRecognizer
和子类UICollectionViewDiffableDataSource
以便使用它的canMoveItemAt:
和moveItemAt:
方法。
重新排序单元格时会发生以下情况:
moveItemAt:
被调用,我更新对象 position 属性并保存 MOCNSFetchedResultsControllerDelegate
的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)
}
}
我对同一问题的解决方案是将 UICollectionViewDiffableDataSource 子类化并在子类中实现 canMoveItemAt 方法以回答 true。 animation 对我来说似乎工作正常,如果 longPressAction 案例 of.ended 做了三件事:
更新 model
调用 dateSource.collectionView(..moveItemAt:..)
运行你的 dataSource.apply
拖拽行为的其他常用方法也必须实现,看起来你已经完成了。 仅供参考 - 这些方法在 UICollectionView 的“交互式重新排序项目”部分中有详细记录。 https://developer.apple.com/documentation/uikit/uicollectionview
class PGLDiffableDataSource: UICollectionViewDiffableDataSource<Int, Int> {
override func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
return true
}
}
无需子类。 从 iOS 14.0 开始,UICollectionViewDiffableDataSource 支持您可以实现的重新排序处理程序。
let data_source = UICollectionViewDiffableDataSource<MySection, MyModelObject>( collectionView: collection_view, cellProvider:
{
[weak self] (collection_view, index_path, video) -> UICollectionViewCell? in
let cell = collection_view.dequeueReusableCell( withReuseIdentifier: "cell", for: index_path ) as! MyCollectionViewCell
if let self = self
{
//setModel() is my own method to update the view in MyCollectionViewCell
cell.setModel( self.my_model_objects[index_path.item] )
}
return cell
})
// Allow every item to be reordered as long as there's 2 or more
diffable_data_source.reorderingHandlers.canReorderItem =
{
item in
my_model_objects.count >= 2 return true
}
//Update your model objects before the reorder occurs.
//You can also use didReorder, but it might be useful to have your
//model objects in the correct order before dequeueReusableCell() is
//called so you can update the cell's view with the correct model object.
diffable_data_source.reorderingHandlers.willReorder =
{
[weak self] transaction in
guard let self = self else { return }
self.my_model_objects = transaction.finalSnapshot.itemIdentifiers
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.