I am using performBatchUpdates() to update my collection view, where I am doing a complete refresh, i.e. delete whatever was in it and re-insert everything. The batch updates are done as part of an Observer which is attached to a NSMutableArray
(bingDataItems
).
cellItems is the array containing items that are or will be inserted into the collection view.
Here is the code:
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { cultARunner *_cultARunner = [cultARunner getInstance]; if ( [[_cultARunner bingDataItems] count] ) { [self.collectionView reloadData]; [[self collectionView] performBatchUpdates: ^{ int itemSize = [cellItems count]; NSMutableArray *arrayWithIndexPaths = [NSMutableArray array]; // first delete the old stuff if (itemSize == 0) { [arrayWithIndexPaths addObject: [NSIndexPath indexPathForRow: 0 inSection: 0]]; } else { for( int i = 0; i < cellItems.count; i++ ) { [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; } } [cellItems removeAllObjects]; if(itemSize) { [self.collectionView deleteItemsAtIndexPaths:arrayWithIndexPaths]; } // insert the new stuff arrayWithIndexPaths = [NSMutableArray array]; cellItems = [_cultARunner bingDataItems]; if ([cellItems count] == 0) { [arrayWithIndexPaths addObject: [NSIndexPath indexPathForRow: 0 inSection: 0]]; } else { for( int i = 0; i < [cellItems count]; i++ ) { [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; } } [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths]; } completion:nil]; } }
I get this error, but not all of the times (why ?)
2012-12-16 13:17:59.789 [16807:19703] *** Assertion failure in -[UICollectionViewData indexPathForItemAtGlobalIndex:], /SourceCache/UIKit_Sim/UIKit-2372/UICollectionViewData.m:442 2012-12-16 13:17:59.790 [16807:19703] DEBUG: request for index path for global index 1342177227 when there are only 53 items in the collection view
I checked the only thread that mentioned the same problem here: UICollectionView Assertion failure, but it is not very clear i.e. doing [collectionview reloadData]
is not advisable in the performBatchUpdates()
block.
Any suggestions on what might be going wrong here ?
Finally! Ok, here's what was causing this crash for me.
As previously noted, I was creating supplementary views in order to provide custom-styled section headers for my collection view.
The problem is this: it appears that the indexPath of a supplementary view MUST correspond to the indexPath of an extant cell in the collection. If the supplementary view's index path has no corresponding ordinary cell, the application will crash. I believe that the collection view attempts to retrieve information for a supplementary view's cell for some reason during the update procedure. It crashes when it cannot find one.
Hopefully this will solve your problem too!
This is the proper workaround to this crash:
Each of your supplementary views are associated with a certain index path. If you don't have a cell at that index path (initial load, you've deleted the row, etc), return a height of 0 for your supplementary view via your layout's delegate.
So, for a flow layout, implement UICollectionViewDelegateFlowLayout's
(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
method (and the corresponding footer method, if you're using footers) with the following logic
if ( you-have-a-cell-at-the-row-for-this-section ) return myNormalHeaderSize; else return CGSizeMake( 0,0 );
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With