I m getting this error on performing insertItemsAtIndexPaths
in UICollectionView
Assertion failure in:
-[UICollectionViewD
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.
I ran into this problem as well. Here's what happened to me:
initWithCollectionViewLayout:
, was initializing my NSFetchedResultsController
.NSManagedObjects
, add them to my NSManagedObjectContext
, which has the main thread's NSManagedObjectContext
as a parentContext
.NSFetchedResultsController
pick up the changes and queue them up.- (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!