简体   繁体   中英

Preventing crash in UICollectionView

Our app has UICollectionView and its dataSource dictionary is regularly updated. We never know when next update will happen. Collection View reload method could be called after user taps a button or it could happen asynchronous after network request success. Given above information we have the risk to have a race condition while reloading collection view and updating its data source at the same time. We even registered the following crash and we believe its happened because of the race condition described above. The crash message:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

The method which cause the crash: collectionViewLayout sizeForItemAtIndexPath: .

This method calculates height for collection View's section depending on items count in the sectionWithProducts . It crashes because dataSource count is smaller than indexPath.row . And the line causing the crash:

NSArray *sectionWithProducts = self.dataSource[indexPath.row];

Following lines called before crash happened:

[self.collectionView setCollectionViewLayout:[self flowLayout] animated:NO];
[self.collectionView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.collectionView reloadData];

To prevent this we decided to put the only line of code which updates data source into main thread.

// 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;
});

We had lots of [self.collectionView reloadData] in our code. Is it worth to run them on main thread as well? It happened quickly so it shouldn't block UI for long.

Is UICollectionViewDelegateFlowLayout delegate methods with indexPath property always called on background queue?

First of all, all UIKIT methods should be called on the main thread including reloadData. This though won't solve your crash. Secondly, somewhere in your code there is a race condition where you are calling reloadData and changing the data source simultaneously and you need to figure out where it is happening. This is what i can say without seeing the actual code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM