UICollectionView Assertion failure

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

I m getting this error on performing insertItemsAtIndexPaths in UICollectionView

Assertion failure in:

-[UICollectionViewD         


        
相关标签:
14条回答
  • 2020-11-29 18:17

    My collection view was getting items from two data sources and updating them caused this issue. My workaround was to queue the data update and collection view reload together:

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
    
                    //Update Data Array
                    weakSelf.dataProfile = [results lastObject]; 
    
                    //Reload CollectionView
                    [weakSelf.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
     }];
    
    0 讨论(0)
  • 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 <NSFetchedResultsSectionInfo>)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];
    }
    
    0 讨论(0)
  • 2020-11-29 18:19

    Check that you're returning the correct value in numberOfSectionsInCollectionView:

    The value I was using to calculate sections was nil, thus 0 sections. This caused the exception.

    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
        NSInteger sectionCount = self.objectThatShouldHaveAValueButIsActuallyNil.sectionCount;
    
        // section count is wrong!
    
        return sectionCount;
    }
    
    0 讨论(0)
  • 2020-11-29 18:21

    In my case, the problem was the way I was creating my NSIndexPath. For example, to delete the 3rd cell, instead of doing :

    NSIndexPath* indexPath = [NSIndexPath indexPathWithIndex:2];
    [_collectionView deleteItemsAtIndexPaths:@[indexPath]];
    

    I needed to do :

    NSIndexPath* indexPath = [NSIndexPath indexPathForItem:2 inSection:0];
    [_collectionView deleteItemsAtIndexPaths:@[indexPath]];
    
    0 讨论(0)
  • 2020-11-29 18:22

    The workaround that actually works is to return a height of 0 if the cell at your supplementary view's index path is not there (initial load, you've deleted the row, etc). See my answer here:

    https://stackoverflow.com/a/18411860/917104

    0 讨论(0)
  • 2020-11-29 18:25

    I hit this problem myself. All the answers here seemed to present problems, except for Alex L's. Referring the update seemed to be tha answer. Here is my final solution:

    - (void)addItem:(id)item {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            if (!_data) {
                _data = [NSMutableArray arrayWithObject:item];
            } else {
                [_data addObject:item];
            }
            [_collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:_data.count-1 inSection:0]]];
        }];
    }
    
    0 讨论(0)
提交回复
热议问题