ios – 如果dataSource计数可能更改,可以使用reloadItemsAtIndexPaths和reloadData吗?

前端之家收集整理的这篇文章主要介绍了ios – 如果dataSource计数可能更改,可以使用reloadItemsAtIndexPaths和reloadData吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_404_0@
我正在调查一个崩溃的bug与 UICollectionView通过Crashlytics通常采取这种形式:

Fatal Exception: NSInternalInconsistencyException Invalid update:
invalid number of items in section 0. The number of items contained in
an existing section after the update (25) must be equal to the number
of items contained in that section before the update (27),plus or
minus the number of items inserted or deleted from that section (1
inserted,1 deleted) and plus or minus the number of items moved into
or out of that section (0 moved in,0 moved out).

我相信这是因为我有一个collectionView定期刷新自己的数据从服务器,并且服务器的数据可能有更多或更少的项目,而不是包含在客户端UICollectionViewDataSource.

当我从服务器获取新数据时,我在集合视图中调用reloadData.

然而,有可能的是,由于用户在网络下载完成之前与我的收藏视图进行交互,所以我之前已经打过reloadItemsAtIndexPaths. reloadItemsAtIndexPaths似乎不会完成至少几百ms和许多处理器周期.因此,当dataSource在reloadItemsAtIndexPaths的中间被更新时,这个崩溃.

reloadItemsAtIndexPath有“立即”形式吗?或者我必须总是在给出我的用例的reloadData,这似乎立即更新一切,并将UICollectionView保持在一个良好的状态.

编辑

根据TwoStraws的建议,我已经完成了以下工作:

// Prevent data source from batch updating while we work
    self.dataSource.locked = YES;

    [self.collectionView performBatchUpdates:^{
        [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
    } completion:^(BOOL finished) {
        self.dataSource.locked = NO;
    }];

然后在我的数据源类中,从服务器收到结果后,我总是调用assignResults:

- (void)assignResults:(NSMutableArray *)newResults {
    if (!self.locked) {
        self.results = newResults;
        [self.delegate handleDataSourceUpdated:self];
    } else {
        self.pendingResults = newResults;
    }
}

- (void)setLocked:(BOOL)locked {
    _locked = locked;

    if (!locked && self.pendingResults) {
        [self assignResults:self.pendingResults];
        self.pendingResults = nil;
    }
}

如您所见,结果只有在数据源未锁定的情况下才会被分配;否则在数据源被UICollectionViewController解锁时分配.请注意,所有这些方法都发生在主线程上,所以我不需要担心我的布尔属性的同步,被锁定.

解决方法

竞争条件总是复杂的问题,我确信你知道.如果我正确理解你的意思,那么在修改收集视图的数据源时,它仍然在尝试重新加载本身,这意味着解决方案是保留一个单独的数据存储,它们被原子地复制到集合视图的数据源.

所以:

>收集视图从数据源A读取.
>网络写入数据源B.
>在你指定的一点上,一下子将B复制成A.
>告诉收集视图重新加载.

这样收集视图就不用担心竞争条件 – 它总是从一个固定的数据集中读取.

猜你在找的iOS相关文章