如何从UICollectionView performBatchUpdates中的断言失败中优雅地恢复:

时间:2014-01-23 06:01:17

标签: ios objective-c uicollectionview

我有一个像这样更新的UICollectionView:

[self.collectionView performBatchUpdates:^{
    [self.collectionView deleteItemsAtIndexPaths:pathsRemoved];
    [self.collectionView insertItemsAtIndexPaths:pathsAdded];
}

通常情况下,这很好用,但在某些情况下,数据源计数与原始项目数不匹配 - 路径数量已删除+已添加路径数量。

因此,我将此代码包装在@ try / @ catch块中,然后调用[self.collectionView reloadData]。

然而,最终发生的事情是,重新加载数据后,布局变得混乱;之前存在的细胞(在屏幕上方的细胞上,但在屏幕外)不再显示。集合视图的内容大小是正确的,我可以向上向上滚动,但只能看到重新加载时屏幕上的单元格。

有趣的是,Reveal.app显示其他细胞确实存在,但是隐藏了;我有一种预感,这是一个红色的鲱鱼,并且这里有一些视图缓存,但是细胞仍然列在Reveal中。

我已经尝试使布局无效,调用layoutIfNeeded,以及我找到的各种子流的布局技巧,并没有修复它。

我通过做自己的良性断言来解决问题,并进行检查以确保计数加起来。如果他们这样做,执行BundUpdates。否则,不要打扰,只是重新加载。这是有效的,因为我们完全绕过了performBatchUpdates:但我不得不问:

是否有更好的方法可以从performBatchUpdates中抛出的断言异常中优雅地恢复:?或者是UICollectionViews只是错误(仍然在iOS 7上)。

1 个答案:

答案 0 :(得分:2)

我只是想办法解决这个问题!

我试着把performBatchUpdates:代码包装在调用[collectionView reloadData]的@ try / @ catch块中。

然后我意识到当我的ViewController被取消分配时,问题也消失了,而collectionView也是。

所以我找到了丑陋的解决方案(但正在工作):杀死旧的collectionView并在catch块中创建一个新的。

@try {
    [collectionView performBatchUpdates:^ {
        // Do your stuff
    }];

}
@catch (NSException *exception) {
    UIView *oldSuperview = self.collectionView.superview;

    [self.collectionView removeFromSuperview];

    self.collectionView = [[UICollectionView alloc] initWithFrame:self.collectionView.frame collectionViewLayout:self.collectionView.collectionViewLayout];

    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    // set other collectionView's properties here

    [oldSuperview addSubview:self.collectionView];
}

我知道这很糟糕,但它救了我!