UICollectionView crashes when insert, reload, insert are called in rapid succession

Originator:mike.ferenduros
Number:rdar://27354858 Date Originated:14-Jul-2016
Status:Closed Resolved:Fixed in iOS 10 beta 4
Product:UIKit Product Version:9.3
Classification:Crash Reproducible:Always
 
Summary:
Performing a sequence of insertItems, reloadData, insertItems, with an interval of 0.1s between each operation, will trigger an assert within UIKit

Steps to Reproduce:
Open and run the attached project under iOS 9.3 (last tested in the 9.3 simulator).

Briefly:
 - Create a UICollectionView with a counter for the number of items, initially zero.
 - Insert a single item with insertItemsAtIndexPaths at item index 0
 - Wait 0.1s
 - Reload the collection-view using reloadData
 - Wait 0.1s
 - Insert a second item with insertItemsAtIndexPaths at item index 1

Expected Results:
I would expect the collection view to end up with two items.

Actual Results:
An assert is triggered in the second insertItemsAtIndexPaths call, with a message like "request for index path for global index 1152930280101002667 when there are only 2 items in the collection view"

Version:
iOS 9.3.2, Xcode 7.3.1

Notes:
Replacing 'reloadData' with 'reloadSections' behaves correctly.
Increasing the delay between calls to 0.2s or higher behaves correctly.

Configuration:
iPhone Simulator, iPhone 6 

Attachments:
'CVCrasher.zip' and 'stack.txt' were successfully uploaded.



Relevant snippet from attached project:

@interface ViewController : UICollectionViewController
{
    int numItems;
}

@end

@implementation ViewController

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self insert];
}

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return numItems;
}

- (void)insert
{
    numItems++;
    [self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:numItems-1 inSection:0]]];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100*NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
        [self reload];
    });
}

- (void)reload
{
    numItems = 1;
    [self.collectionView reloadData];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100*NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
        [self insert];
    });
}

@end

Comments

Fixed in iOS 10 beta 4

Now just triggers debug messages: [Assert] attempt to add identical layout attributes to list of on screen attributes to animated [Assert] attempt to create two animations for new global item index 0

By mike.ferenduros at Aug. 2, 2016, 2:52 p.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!