我的应用有两个CollectionViewController
个。在给定时间只能看到一个。
我在故事板上创建了以下结构:两个容器视图相互叠加。每个容器视图都嵌入了CollectionViewController
。特定容器视图的可见性决定了哪个collectionViewController可见。
这就是问题所在。两个CollectionViewController
都是并行接收数据,但iOS有一个错误,如果一个CollectionViewController在performBatchUpdates
不可见的情况下尝试执行插入操作时会导致应用程序崩溃。
为了防止这种情况,我在CollectionViewController
上创建了一个BOOL标志,这样他们就可以知道它们是否可见并执行与否performBatchUpdates
。类似的东西:
if (self.isThisCollectionViewVisible == NO) return;
[self.collectionView performBatchUpdates:^{
// bla bla... perform insert,m remove...
这解决了部分问题。但是应用程序在以下情况下继续崩溃:如果我点击按钮切换到不可见的CollectionViewController
,使其在接收更新时可见。
我的意思是:让我们先调用A
第一个CollectionViewController
和B
。 A
可见,此时B
不可见。 B
开始接收数据并尝试执行performBatchUpdates
,但由于它不可见,if (self.isThisCollectionViewVisible == NO) return;
阻止performBatchUpdates
运行,没关系。现在,我将A
置于不可见状态,B
可见。此时,标记self.isThisCollectionViewVisible
设置为YES
,performBatchUpdates
使应用程序崩溃并出现此错误:
*断言失败 - [CollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:],/ BuildRoot / Library / Cache / com.apple.xbs / Source / UIKit / UIKit-3512.60.7 / UICollectionView.m:4625 * 由于未捕获的异常终止应用' NSInternalInconsistencyException',原因:'无效更新:无效 第0节中的项目数。包含在项目中的项目数 更新后的现有部分(76)必须等于数量 更新前的该部分中包含的项目(70),加号或减号 从该部分插入或删除的项目数(插入5个, 2删除)并加上或减去移入或移出的项目数 该部分(0移入,0移出)。'
我认为CollectionViewController
尚未准备好并已更新为能够执行performBatchUpdates
...这不是以前不更新数据源的问题,因为它正在更新
我可以采取哪些措施来防止这种情况发生?
注意:我特别注意到这次崩溃的一些奇怪之处。它说插入了5个元素,删除了2个,但实际上插入了3个元素,0个被删除,2个崩溃发生时更改了。
答案 0 :(得分:17)
我添加self.collectionView.numberOfItemsInSection(0)
修复了崩溃。
当项目不可见时,collectionView在插入项目时会出现问题。
好像我并不孤单,我的解决方案:http://www.openradar.me/15262692
答案 1 :(得分:3)
此崩溃告诉您,您没有更新数据源以进行收集。执行performBatchUpdates
后,您需要更新dataSource(数组或字典)并重新加载集合视图数据。
无效更新:第0部分中的项目数无效。更新后现有部分中包含的项目数(76)必须等于更新前该部分中包含的项目数(70),或者减去从该部分插入或删除的项目数(插入5个,删除2个),加上或减去移入或移出该部分的项目数(0移入,0移出)。'
正如苹果文档中所述
在批处理操作中插入之前处理删除。这意味着 删除的索引是相对于索引处理的 批处理操作之前的集合视图的状态,以及 插入的索引相对于索引进行处理 在批处理操作中的所有删除之后的状态。
因此,在插入之前移动更改,这将是一招!
答案 2 :(得分:0)
今天遇到了同样的错误,对于我来说,在performBatchUpdates块中替换了这个:
NSArray *selectedItemsIndexPaths = [self.collectionView indexPathsForSelectedItems];
用这个:
NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:self.selectIndex inSection:0];
NSArray *selectedItemsIndexPaths = @[selectedIndexPath];
自己维护索引,现在没关系。如果您已更新数据源,则错误不应与数据源相关联。它可能与细胞的重复使用有关。