问题
I am struggling to integrate UICollectionView and NSFetchedResultsControllerDelegate in this particular case.
In my view controller, I fetch a Parent entity, but display its multiple Child entities in the collection view. When creating a new Parent entity in this view controller (with insertNewObjectForEntityForName) and automatically creating a Child entity and adding it to the parent entity with addChildObject, I can add more Child entities by pressing a button, and save the object successfully. Unfortunately, for some reason the NSFetchedResultsControllerDelegate methods are not called, specifically, controllerDidChangeContent is never called and the collection view doesn't get updated.
When I fetch an already existing Parent entity, and then try to change it by adding new Child objects, the app crashes with the following exception:
*** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3505.17/UICollectionView.m:4211
And gives out this error in the end:
CoreData: error: Serious application error. An exception was caught
from the delegate of NSFetchedResultsController during a call to
controllerDidChangeContent:. Invalid update: invalid number of items
in section 0. The number of items contained in an existing section
after the update (5) must be equal to the number of items contained in
that section before the update (4), plus or minus the number of items
inserted or deleted from that section (1 inserted, 1 deleted) and plus
or minus the number of items moved into or out of that section (0 moved
in, 0 moved out). with userInfo (null)
What puzzles me the most, is that it shows that there is a deleted item in (1 inserted, 1 deleted), when, in fact, I am only adding an item (initializing a Child entity with insertNewObjectForEntityForName and adding it with [parent addChildObject:child].
In all these cases, I am not saving the context. I expect adding objects to the parent entity to trigger NSFetchedResultsControllerDelegate methods.
FetchResultsController setup code:
- (NSFetchedResultsController *) fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [self emojiFetchRequest];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self managedObjectContext] sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
Initializing parent object in viewWillAppear:
[[self fetchedResultsController] performFetch:&error];
id fetchedObject = [[[self fetchedResultsController] fetchedObjects] firstObject];
if (fetchedObject != nil) {
self.parent = (Parent *)fetchedObject;
self.navigationItem.title = self.parent.name;
} else {
self.navigationItem.title = @"New parent";
self.parent = [NSEntityDescription insertNewObjectForEntityForName:@"Parent" inManagedObjectContext:[self managedObjectContext]];
Child *child = [NSEntityDescription insertNewObjectForEntityForName:@"Child" inManagedObjectContext:[self managedObjectContext]];
[self.parent addFramesObject:frame];
}
Adding new child objects:
Child *child = [NSEntityDescription insertNewObjectForEntityForName:@"Child" inManagedObjectContext:[self managedObjectContext]];
[self.parent addChildrenObject:child];
[self.collectionView reloadData]; // if this isn't done, the crash happens
// but this can't animate changes
Core Data Model:
Is there a way I can see those objects? I've tried logging didChangeObject, and I only see one insert. I am not deleting anything. If anyone has any other ideas, I'd be glad to hear them.
EDIT:
If I call [self.collectionView reloadData] after adding the objects, everything seems to work correctly without crashing. But, it would be nice for the changes to be animated, which cannot be done with reloadData, and I sense there is something fundamentally wrong with what I'm doing and I would like to fix it.
回答1:
Best solution: Fetch the Child entity in your fetched results controller, filter by parent.
For inserts, use the plain vanilla implementation of the NSFetchedResultsControllerDelegate. This will provide a nice animation or let you add your own.
来源:https://stackoverflow.com/questions/34037873/how-to-check-inserted-and-deleted-items-in-uicollectionview-seeing-unexpected-d