【问题标题】:How to check inserted and deleted items in UICollectionView, seeing unexpected deleted item如何检查 UICollectionView 中插入和删除的项目,看到意外删除的项目
【发布时间】:2015-12-02 08:21:56
【问题描述】:

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

在我的视图控制器中,我获取了一个父实体,但在集合视图中显示了它的多个子实体。在此视图控制器中创建新的父实体(insertNewObjectForEntityForName)并自动创建一个子实体并将其添加到具有addChildObject 的父实体中时,我可以通过按一个按钮添加更多子实体,并成功保存对象.不幸的是,由于某种原因,NSFetchedResultsControllerDelegate 方法没有被调用,具体来说,controllerDidChangeContent 从未被调用,并且集合视图也没有得到更新。

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

*** 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初始化一个Child实体并用@987654333添加它@。

在所有这些情况下,我都没有保存上下文。我希望将对象添加到父实体以触发 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

核心数据模型:

有没有办法让我看到这些对象?我试过记录didChangeObject,但我只看到一个插入。我没有删除任何东西。如果有人有任何其他想法,我很乐意听到。

编辑

如果我在添加对象后调用[self.collectionView reloadData],一切似乎都可以正常工作而不会崩溃。但是,如果更改动画效果会很好,reloadData 无法做到这一点,而且我觉得我所做的事情存在根本性的问题,我想修复它。

【问题讨论】:

  • 显示模型图片、FRC 设置代码和添加新对象的代码
  • @Wain:请看编辑。

标签: ios objective-c core-data nsfetchedresultscontroller


【解决方案1】:

最佳解决方案:在 fetched results 控制器中获取 Child 实体,按 parent 过滤。

对于插入,使用NSFetchedResultsControllerDelegate 的普通实现。这将提供一个不错的动画或让您添加自己的动画。

【讨论】:

  • 感谢您的回答。你能解释一下为什么它是最好的解决方案吗?根据我的理解,NSFetchedResultsControllerDelegate 不监听托管对象上下文的变化,只要将实体添加到上下文中,获取实体的顺序不相关?
  • 为什么是“最佳”?因为我想不出更好或更简单的方法。 ;-) - 获取对象的顺序确实是随机的,但是您的 FRC 获取请求可以有一个 排序描述符 来处理显示顺序。 -- 所以以防万一有一些混淆:我所指的获取是由 fetched results controller 完成的。
猜你喜欢
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 1970-01-01
  • 2013-04-24
相关资源
最近更新 更多