13

我的应用程序有两个CollectionViewControllers。在给定时间只有一个可见。

我在情节提要上创建了以下结构:两个容器视图相互叠加。每个容器视图都有一个CollectionViewController嵌入的。特定容器视图的可见性决定了哪个 collectionViewController 可见。

这就是问题。两个s 都在并行接收数据,但是 iOS 有一个错误,如果一个 CollectionViewController在不可见的情况下CollectionViewController尝试执行插入操作,则会导致应用程序崩溃。performBatchUpdates

为了防止这种情况,我在两个CollectionViewControllers 上都创建了一个 BOOL 标志,这样他们就可以知道它们是否可见并执行performBatchUpdates. 就像是:

if (self.isThisCollectionViewVisible == NO) return;

[self.collectionView performBatchUpdates:^{
   // bla bla... perform insert,m remove...

这解决了部分问题。但是该应用程序在以下情况下继续崩溃:如果我点击按钮切换到不CollectionViewController可见,使其在接收更新时可见。

我的意思是:让我们调用A第一个CollectionViewControllerB第二个。A此时可见和B不可见。B开始接收数据并尝试执行performBatchUpdates但由于它是不可见的,因此if (self.isThisCollectionViewVisible == NO) return;阻止performBatchUpdates运行,这很好。现在我让A隐形和B可见。此时标志self.isThisCollectionViewVisible设置为YES并使performBatchUpdates应用程序崩溃并出现以下错误:

* 断言失败 -[CollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.7/UICollectionView.m:4625 *由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序',原因:'无效更新:第0节中的项目数无效。更新后现有节中包含的项目数(76)必须等于更新前该节中包含的项目数(70),加上或减去从该部分插入或删除的项目数(插入 5 个,删除 2 个),加上或减去移入或移出该部分的项目数(0 移入,0 移出)。

我认为CollectionViewController真的还没有准备好和更新能够做一个performBatchUpdates......这不是因为它正在更新而之前不更新数据源的问题。

我可以做哪些检查来防止这种情况发生?

注意:我特别注意到这次崩溃有一些奇怪的地方。它说正在插入 5 个元素并删除了 2 个元素,但实际上当崩溃发生时,正在插入 3 个元素,0 个元素被删除,2 个元素被更改。

4

3 回答 3

21

对我来说,添加self.collectionView.numberOfItemsInSection(0)修复了崩溃。collectionView 在不可见时插入项目时出现问题。

似乎我并不孤单我的解决方案:http ://www.openradar.me/15262692

于 2016-05-19T12:50:03.017 回答
3

此崩溃告诉您您没有更新数据源以进行收集。您需要更新数据源(数组或字典)并在执行后重新加载集合视图数据performBatchUpdates

无效更新:第 0 节中的项目数无效。更新后现有节中包含的项目数 (76) 必须等于更新前该节中包含的项目数 (70),加上或减去数字从该部分插入或删除的项目数(5 个插入,2 个删除)加上或减去移入或移出该部分的项目数(0 移入,0 移出)。

正如苹果文档中所写

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

因此,在插入之前移动更改,这将是诀窍!

于 2016-03-31T13:18:26.383 回答
1

今天遇到了同样的错误,对我来说,在 performBatchUpdates 块中替换这个:

  NSArray *selectedItemsIndexPaths = [self.collectionView indexPathsForSelectedItems];

有了这个:

  NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:self.selectIndex inSection:0];
  NSArray *selectedItemsIndexPaths = @[selectedIndexPath];

自己维护索引,现在可以了。如果您已更新数据源,则该错误不应与数据源相关联。这可能与细胞的重用有关。

于 2016-05-25T09:50:32.923 回答