如何在UICollectionView performBatchUpdates块中排序移动,插入,删除和更新?

时间:2016-07-26 18:55:04

标签: ios objective-c swift uicollectionview uikit

在我的UICollectionView中,我使用一个简单的自定义对象数组来生成和显示单元格。偶尔数据会发生变化,我希望一次性对变化进行动画制作。我选择通过跟踪第二个数组中的所有更改,对两者进行区分,并在performBatchUpdates块内部生成一组移动,插入,删除和更新操作来选择执行此操作。我现在意识到在同一个块中完成所有这些操作非常棘手,因为你不得不担心索引操作的顺序。事实上,this issue的已接受答案是错误的(但在评论中已得到纠正)。

文档似乎很缺乏,但它涵盖了一个案例:

  

在批处理操作中插入之前处理删除。这意味着   删除的索引是相对于索引处理的   批处理操作之前的集合视图的状态,以及   插入的索引相对于索引进行处理   在批处理操作中的所有删除之后的状态。

然而,该文件并未谈及何时处理移动。如果我在同一moveItemAtIndexPath中调用deleteItemsAtIndexPathsperformBatchUpdates,移动索引是否应该相对于删除前或删除后的订单? insertItemsAtIndexPaths怎么样?

最后,我遇到了在同一操作中调用reloadItemsAtIndexPathsmoveItemAtIndexPath的问题:

  

致命异常:NSInternalInconsistencyException尝试删除   并重新加载相同的索引路径

有没有办法在同一performBatchUpdates进行我想要的所有操作?如果是,那么更新相对于其他更新的处理顺序是什么?如果没有,人们通常会做什么?在完成所有其他操作后重新加载数据?之前?如果所有动画都在一个阶段发生,我更喜欢。

2 个答案:

答案 0 :(得分:8)

对于移动操作,from indexPath是预删除索引,to indexPath是删除后索引。仅应为尚未插入,删除或移动的indexPath指定重新加载。这可能是您看到NSInternalInconsistencyException

的原因

验证操作的一种方便的方法是正确设置的:重载,插入和移动到索引路径的集合不应该有任何重复,并且重载,删除和移动索引路径集不应该有任何重复

更新:

您移动的项目似乎也未更新,但仅移动。因此,如果您需要更新和移动项目,则可以在批量更新之前或之后执行重新加载(取决于数据源的状态)。

答案 1 :(得分:6)

Mark's answer是正确的。我建议您观看WWDC's 2018 Session 225 "A Tour of UICollectionView",以获得Apple工程师的完整解释。

您可以skip to the 33'36" mark来获得有趣的位置。

Collection View Updates Coalescing Slide

视频摘要

  • 2列出:“原始项目”(任何更改之前)和“最终项目”(所有更改之后);
  • 原始索引→原始项目中的索引
  • 最终索引→最终项目中的索引

PerformBatchUpdates中的操作顺序

  1. 删除→始终使用原始索引(降序使用)
  2. 插入→始终使用最终索引(将以升序使用)
  3. 移动→从=原始索引;到=最终索引
  4. 重新加载→在引擎盖下,它删除然后插入。索引=原始索引。您无法重新加载已移动的项目。

要重新加载已移动的项目,请在PerformBatchUpdates内的单独PerformWithoutAnimation中调用所有重新加载(因为重新加载从不动画)。