在我的UICollectionView
中,我使用一个简单的自定义对象数组来生成和显示单元格。偶尔数据会发生变化,我希望一次性对变化进行动画制作。我选择通过跟踪第二个数组中的所有更改,对两者进行区分,并在performBatchUpdates
块内部生成一组移动,插入,删除和更新操作来选择执行此操作。我现在意识到在同一个块中完成所有这些操作非常棘手,因为你不得不担心索引操作的顺序。事实上,this issue的已接受答案是错误的(但在评论中已得到纠正)。
文档似乎很缺乏,但它涵盖了一个案例:
在批处理操作中插入之前处理删除。这意味着 删除的索引是相对于索引处理的 批处理操作之前的集合视图的状态,以及 插入的索引相对于索引进行处理 在批处理操作中的所有删除之后的状态。
然而,该文件并未谈及何时处理移动。如果我在同一moveItemAtIndexPath
中调用deleteItemsAtIndexPaths
和performBatchUpdates
,移动索引是否应该相对于删除前或删除后的订单? insertItemsAtIndexPaths
怎么样?
最后,我遇到了在同一操作中调用reloadItemsAtIndexPaths
和moveItemAtIndexPath
的问题:
致命异常:NSInternalInconsistencyException尝试删除 并重新加载相同的索引路径
有没有办法在同一performBatchUpdates
进行我想要的所有操作?如果是,那么更新相对于其他更新的处理顺序是什么?如果没有,人们通常会做什么?在完成所有其他操作后重新加载数据?之前?如果所有动画都在一个阶段发生,我更喜欢。
答案 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来获得有趣的位置。
PerformBatchUpdates
中的操作顺序要重新加载已移动的项目,请在PerformBatchUpdates
内的单独PerformWithoutAnimation
中调用所有重新加载(因为重新加载从不动画)。