How to check inserted and deleted items in UICollectionView, seeing unexpected deleted item

流过昼夜 提交于 2019-12-12 05:26:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!