UICollectionView Assertion failure

前端 未结 14 2202
别那么骄傲
别那么骄傲 2020-11-29 17:27

I m getting this error on performing insertItemsAtIndexPaths in UICollectionView

Assertion failure in:

-[UICollectionViewD         


        
14条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-29 18:19

    Here's a solution for this bug I've been using in my projects I thought I'd post here in case any found it valuable.

    @interface FetchedResultsViewController ()
    
    @property (nonatomic) NSMutableIndexSet *sectionsToAdd;
    @property (nonatomic) NSMutableIndexSet *sectionsToDelete;
    
    @property (nonatomic) NSMutableArray *indexPathsToAdd;
    @property (nonatomic) NSMutableArray *indexPathsToDelete;
    @property (nonatomic) NSMutableArray *indexPathsToUpdate;
    
    @end
    
    #pragma mark - NSFetchedResultsControllerDelegate
    
    
    - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
    {
        [self resetFetchedResultControllerChanges];
    }
    
    
    - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo
               atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
    {
        switch(type)
        {
            case NSFetchedResultsChangeInsert:
                [self.sectionsToAdd addIndex:sectionIndex];
                break;
    
            case NSFetchedResultsChangeDelete:
                [self.sectionsToDelete addIndex:sectionIndex];
                break;
        }
    }
    
    
    - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
           atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
          newIndexPath:(NSIndexPath *)newIndexPath
    {
        switch(type)
        {
            case NSFetchedResultsChangeInsert:
                [self.indexPathsToAdd addObject:newIndexPath];
                break;
    
            case NSFetchedResultsChangeDelete:
                [self.indexPathsToDelete addObject:indexPath];
                break;
    
            case NSFetchedResultsChangeUpdate:
                [self.indexPathsToUpdate addObject:indexPath];
                break;
    
            case NSFetchedResultsChangeMove:
                [self.indexPathsToAdd addObject:newIndexPath];
                [self.indexPathsToDelete addObject:indexPath];
                break;
        }
    }
    
    
    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    {
        if (self.sectionsToAdd.count > 0 || self.sectionsToDelete.count > 0 || self.indexPathsToAdd.count > 0 || self.indexPathsToDelete > 0 || self.indexPathsToUpdate > 0)
        {
            if ([self shouldReloadCollectionViewFromChangedContent])
            {
                [self.collectionView reloadData];
    
                [self resetFetchedResultControllerChanges];
            }
            else
            {
                [self.collectionView performBatchUpdates:^{
    
                    if (self.sectionsToAdd.count > 0)
                    {
                        [self.collectionView insertSections:self.sectionsToAdd];
                    }
    
                    if (self.sectionsToDelete.count > 0)
                    {
                        [self.collectionView deleteSections:self.sectionsToDelete];
                    }
    
                    if (self.indexPathsToAdd.count > 0)
                    {
                        [self.collectionView insertItemsAtIndexPaths:self.indexPathsToAdd];
                    }
    
                    if (self.indexPathsToDelete.count > 0)
                    {
                        [self.collectionView deleteItemsAtIndexPaths:self.indexPathsToDelete];
                    }
    
                    for (NSIndexPath *indexPath in self.indexPathsToUpdate)
                    {
                        [self configureCell:[self.collectionView cellForItemAtIndexPath:indexPath]
                                atIndexPath:indexPath];
                    }
    
                } completion:^(BOOL finished) {
                    [self resetFetchedResultControllerChanges];
                }];
            }
        }
    }
    
    // This is to prevent a bug in UICollectionView from occurring.
    // The bug presents itself when inserting the first object or deleting the last object in a collection view.
    // http://stackoverflow.com/questions/12611292/uicollectionview-assertion-failure
    // This code should be removed once the bug has been fixed, it is tracked in OpenRadar
    // http://openradar.appspot.com/12954582
    - (BOOL)shouldReloadCollectionViewFromChangedContent
    {
        NSInteger totalNumberOfIndexPaths = 0;
        for (NSInteger i = 0; i < self.collectionView.numberOfSections; i++)
        {
            totalNumberOfIndexPaths += [self.collectionView numberOfItemsInSection:i];
        }
    
        NSInteger numberOfItemsAfterUpdates = totalNumberOfIndexPaths;
        numberOfItemsAfterUpdates += self.indexPathsToAdd.count;
        numberOfItemsAfterUpdates -= self.indexPathsToDelete.count;
    
        BOOL shouldReload = NO;
        if (numberOfItemsAfterUpdates == 0 && totalNumberOfIndexPaths == 1)
        {
            shouldReload = YES;
        }
    
        if (numberOfItemsAfterUpdates == 1 && totalNumberOfIndexPaths == 0)
        {
            shouldReload = YES;
        }
    
        return shouldReload;
    }
    
    - (void)resetFetchedResultControllerChanges
    {
        [self.sectionsToAdd removeAllIndexes];
        [self.sectionsToDelete removeAllIndexes];
        [self.indexPathsToAdd removeAllObjects];
        [self.indexPathsToDelete removeAllObjects];
        [self.indexPathsToUpdate removeAllObjects];
    }
    

提交回复
热议问题