reloadItemsAtIndexPaths

reloadItemsAtIndexPaths

我正在研究通过Crashlytics使用 UICollectionView 崩溃的错误,该错误通常采用以下形式:



我相信这是因为我有一个collectionView,它会定期使用服务器中的数据刷新自身,并且服务器中的数据可能比客户端 UICollectionViewDataSource 中包含的项目更多或更少。

从服务器获取新数据时,我在集合 View 上调用reloadData

但是,由于在网络下载完成之前用户与我的收藏夹 View 的交互,有可能我之前已经调用了 reloadItemsAtIndexPaths reloadItemsAtIndexPaths在至少几百毫秒和许多处理器周期内似乎没有完成。因此,当在reloadItemsAtIndexPaths中间更新dataSource时,将发生此崩溃。

是否有reloadItemsAtIndexPaths的“立即”形式?或者在给定用例的情况下,我必须始终调用 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解锁数据源时分配它们。请注意,所有这些方法都是在主线程上发生的,因此我不必担心 bool 属性locked的同步。

最佳答案

就像您确定的那样,竞赛条件始终是复杂的问题。如果我对您的理解正确,那么您正在修改集合 View 的数据源,而它仍试图重新加载自身,这意味着解决方案是保留一个单独的数据存储,该存储将原子复制到集合 View 的数据源中。

所以:

  • 集合 View 从数据源A中读取。
  • 网络写入数据源B。
  • 在您指定的一点上,一举将B复制到A。
  • 告诉收集 View 重新加载。

  • 这样一来,收集 View 就不必担心种族状况-它始终会从一组固定的数据中读取相关数据。

    10-08 11:41