我们的应用程序具有UICollectionView
其dataSource
字典定期更新。我们永远不知道下一次更新何时发生。用户单击按钮后可以调用Collection View重新加载方法,也可以在网络请求成功后异步发生。鉴于以上信息,在重新加载集合视图并同时更新其数据源时,我们可能会出现竞争状况。我们甚至记录了以下崩溃,并且我们相信由于上述比赛情况,它发生了。崩溃消息:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
导致崩溃的方法:collectionViewLayout sizeForItemAtIndexPath:
。
此方法根据中的项目计数计算集合视图部分的高度sectionWithProducts
。由于dataSource
count小于,因此崩溃indexPath.row
。和导致崩溃的行:
NSArray *sectionWithProducts = self.dataSource[indexPath.row];
在崩溃发生之前调用了以下行:
[self.collectionView setCollectionViewLayout:[self flowLayout] animated:NO];
[self.collectionView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.collectionView reloadData];
为了避免这种情况,我们决定只将更新数据源的代码放入主线程中。
// Always run on main thread in hope to prevent NSRangeException.
// Reloading data should happen only sequential.
dispatch_async(dispatch_get_main_queue(), ^(void) {
self.dataSource = newValue;
});
我们[self.collectionView reloadData]
的代码中有很多。在主线程上运行它们是否值得?它发生得很快,因此不应长时间阻塞UI。
是否总是在后台队列上调用UICollectionViewDelegateFlowLayout
具有indexPath
属性的委托方法?
首先,应在主线程上调用所有UIKIT方法,包括reloadData。这虽然不能解决您的崩溃问题。其次,在代码中的某个地方存在竞争状况,在此情况下,您正在调用reloadData并同时更改数据源,并且需要弄清楚它的发生位置。这就是我看不到实际代码可以说的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句