首页 > 解决方案 > 如何使用异步数据源和单元格注册在 UICollectionView 拖放中实现拖放操作?

问题描述

我有一个UICollectionView绑定到一个UICollectionViewDiffableDataSource,我正在生成快照并将其应用到后台串行队列上的数据源,并使用UICollectionViewCellRegistration. 我正在努力支持通过拖放对集合视图的内容进行重新排序,但我在做什么时遇到了麻烦,collectionView:performDropWithCoordinator:因此重新排序动画看起来是正确的。

通常,我会做这样的事情:

-(void)collectionView:(UICollectionView *)collectionView performDropWithCoordinator:(id<UICollectionViewDropCoordinator>)coordinator
{
  NSIndexPath *sourcePath = (NSIndexPath *)coordinator.items.firstObject.dragItem.localObject;
  NSInteger fromIndex = sourcePath.item;
  NSInteger toIndex = coordinator.destinationIndexPath.item;
  NSNumber *fromItem = [self.datasource itemIdentifierForIndexPath:sourcePath];
  NSNumber *toItem = [self.datasource itemIdentifierForIndexPath:coordinator.destinationIndexPath];

  //Do the move in the data model
  [MyModel moveItemFrom:fromIndex to:toIndex];

  //Do the move in the datasource. This is the data source equivalent of:
  //[collectionView moveItemAtIndexPath:sourcePath toIndexPath:coordinator.destinationIndexPath];

  NSDiffableDataSourceSnapshot *snap = self.datasource.snapshot;
  if (toIndex < fromIndex)
    [snap moveItemWithIdentifier:fromItem beforeItemWithIdentifier:toItem];
  else
    [snap moveItemWithIdentifier:fromItem afterItemWithIdentifier:toItem];

  [self.dataSource applySnapshot:snap animated:YES];

  //Drop the item
  [coordinator dropItem:coordinator.items.firstObject.dragItem toItemAtIndexPath:coordinator.destinationIndexPath];
}

但是因为我的数据源更新发生在后台队列上,所以我至少必须异步进行快照生成和应用程序,并且我也想在那里进行实际的数据模型修改以避免挂起。而且我需要在这个方法中调用主队列dropItem上的协调器。这会导致一个奇怪的动画,其中放置的项目暂时消失(当被调用时)然后重新出现(当数据源在后台队列上更新时)。drop

到目前为止,我最好的想法是使用UICollectionViewDropPlaceholder在集合视图中保留该位置,直到数据源更新。但是要创建一个占位符,我需要一个单元重用标识符(有关 init 方法的文档),而我没有其中一个,因为我正在使用单元注册创建我的单元。

所以我的问题是:我该怎么做performDrop才能使它正常工作?如果占位符是正确的想法,我该如何在这种情况下使用它?

标签: iosuicollectionviewuicollectionviewdiffabledatasourceuicollectionviewdropdelegate

解决方案


推荐阅读