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解锁时分配.请注意,所有这些方法都发生在主线程上,所以我不需要担心我的布尔属性的同步,被锁定.