UICollectionView Assertion failure

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

I m getting this error on performing insertItemsAtIndexPaths in UICollectionView

Assertion failure in:

-[UICollectionViewD         


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

    I've posted a work around for this issue here: https://gist.github.com/iwasrobbed/5528897

    In the private category at the top of your .m file:

    @interface MyViewController ()
    {
        BOOL shouldReloadCollectionView;
        NSBlockOperation *blockOperation;
    }
    @end
    

    Then your delegate callbacks would be:

    - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
    {
        shouldReloadCollectionView = NO;
        blockOperation = [NSBlockOperation new];
    }
    
    - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
               atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
    {
        __weak UICollectionView *collectionView = self.collectionView;
        switch (type) {
            case NSFetchedResultsChangeInsert: {
                [blockOperation addExecutionBlock:^{
                    [collectionView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
                }];
                break;
            }
    
            case NSFetchedResultsChangeDelete: {
                [blockOperation addExecutionBlock:^{
                    [collectionView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
                }];
                break;
            }
    
            case NSFetchedResultsChangeUpdate: {
                [blockOperation addExecutionBlock:^{
                    [collectionView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
                }];
                break;
            }
    
            default:
                break;
        }
    }
    
    - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
    {
        __weak UICollectionView *collectionView = self.collectionView;
        switch (type) {
            case NSFetchedResultsChangeInsert: {
                if ([self.collectionView numberOfSections] > 0) {
                    if ([self.collectionView numberOfItemsInSection:indexPath.section] == 0) {
                        shouldReloadCollectionView = YES;
                    } else {
                        [blockOperation addExecutionBlock:^{
                            [collectionView insertItemsAtIndexPaths:@[newIndexPath]];
                        }];
                    }
                } else {
                    shouldReloadCollectionView = YES;
                }
                break;
            }
    
            case NSFetchedResultsChangeDelete: {
                if ([self.collectionView numberOfItemsInSection:indexPath.section] == 1) {
                    shouldReloadCollectionView = YES;
                } else {
                    [blockOperation addExecutionBlock:^{
                        [collectionView deleteItemsAtIndexPaths:@[indexPath]];
                    }];
                }
                break;
            }
    
            case NSFetchedResultsChangeUpdate: {
                [blockOperation addExecutionBlock:^{
                    [collectionView reloadItemsAtIndexPaths:@[indexPath]];
                }];
                break;
            }
    
            case NSFetchedResultsChangeMove: {
                [blockOperation addExecutionBlock:^{
                    [collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
                }];
                break;
            }
    
            default:
                break;
        }
    }
    
    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    {
        // Checks if we should reload the collection view to fix a bug @ http://openradar.appspot.com/12954582
        if (shouldReloadCollectionView) {
            [self.collectionView reloadData];
        } else {
            [self.collectionView performBatchUpdates:^{
                [blockOperation start];
            } completion:nil];
        }
    }
    

    Credit for this approach goes to Blake Watters.

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

    I ran into this problem as well. Here's what happened to me:

    1. I subclassed UICollectionViewController and, on initWithCollectionViewLayout:, was initializing my NSFetchedResultsController.
    2. Have a shared class fetch results from an NSURLConnection and parse the JSON string (different thread)
    3. Loop through the feed and create my NSManagedObjects, add them to my NSManagedObjectContext, which has the main thread's NSManagedObjectContext as a parentContext.
    4. Save my context.
    5. Have my NSFetchedResultsController pick up the changes and queue them up.
    6. On - (void)controllerDidChangeContent:, I would process the changes and apply them to my UICollectionView.

    Intermittently, I would get the error the OP is getting and couldn't figure out why.

    To fix this issue, I moved the NSFetchedResultsController initialization and performFetch to my - viewDidLoad method and this problem is now gone. No need to call [collectionView reloadData] or anything and all the animations are working properly.

    Hope this helps!

    0 讨论(0)
提交回复
热议问题