如何在UICollectionView中检查插入和删除的项目,看到意外删除的项目

时间:2015-12-02 08:21:56

标签: ios objective-c core-data nsfetchedresultscontroller

我正在努力在这个特殊情况下整合UICollectionViewNSFetchedResultsControllerDelegate

在我的视图控制器中,我获取一个Parent实体,但在集合视图中显示其多个Child实体。在此视图控制器中创建新的Parent实体(使用insertNewObjectForEntityForName)并自动创建Child实体并将其添加到具有addChildObject的父实体时,我可以通过按下按钮添加更多Child实体,并且成功保存对象。遗憾的是,由于某些原因,未调用NSFetchedResultsControllerDelegate方法,具体而言,永远不会调用controllerDidChangeContent,并且集合视图不会更新。

当我获取一个已经存在的Parent实体,然后尝试通过添加新的Child对象来更改它时,该应用程序崩溃时出现以下异常:

*** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:], 
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3505.17/UICollectionView.m:4211

最后给出了这个错误:

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)

最让我感到困惑的是,它显示(1 inserted, 1 deleted)中有一个已删除的项目,事实上,我只是添加一个项目(使用insertNewObjectForEntityForName初始化一个子实体并添加它与[parent addChildObject:child]

在所有这些情况下,我没有保存上下文。我希望将对象添加到父实体以触发NSFetchedResultsControllerDelegate方法。

FetchResultsController设置代码:

- (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;
}

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];
}

添加新的子对象:

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

有没有办法看到那些物品?我已经尝试记录didChangeObject,我只看到一个插入。我没有删除任何东西。如果有人有任何其他想法,我会很高兴听到他们。

修改

如果我在添加对象后调用[self.collectionView reloadData],一切似乎都能正常工作而不会崩溃。但是,对于动画更改是很好的,这不能用reloadData完成,而且我觉得我正在做的事情存在根本性的错误,我想解决它。

1 个答案:

答案 0 :(得分:0)

最佳解决方案:在获取的结果控制器中获取Child实体,按parent进行过滤。

对于插入,请使用NSFetchedResultsControllerDelegate的普通版实现。这将提供一个漂亮的动画或让你添加自己的动画。