【问题标题】:How do you handle section inserts with an NSFetchedResultsController?您如何使用 NSFetchedResultsController 处理节插入?
【发布时间】:2009-10-13 16:19:21
【问题描述】:

我有一个 NSFetchedResultsController 作为我的数据源,并且我在我的自定义 UITableViewController 中实现了 NSFetchedResultsControllerDelegate。我正在使用 sectionNameKeyPath 将我的结果集分成多个部分。

在我的一个方法中,我将几个对象添加到上下文中,所有这些对象都在一个新部分中。在我保存对象的那一刻,委托方法被正确调用。事件顺序:

// -controllerWillChangeContent: fires
[self.tableView beginUpdates]; // I do this

// -controller:didChangeSection:atIndex:forChangeType: fires for section insert
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];

// -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath fires many times
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                withRowAnimation:UITavleViewRowAnimationFade]; // for each cell

// -controllerDidChangeContent: fires after all of the inserts
[self.tableView endUpdates];  // <--- Where things go terribly wrong!!!

在最后一次调用“endUpdates”时,应用程序总是崩溃:

Serious application error.  Exception was caught during Core Data change processing:
[NSCFArray objectAtIndex:]: index (5) beyond bounds (1) with userInfo (null)

似乎表格更新在某种程度上与 NSFetchedResultsController 数据不同步,并且事情发生了变化。我正在关注 NSFetchedResultsControllerDelegate 上的文档,但它不起作用。正确的做法是什么?

更新:我创建了一个显示此错误的测试项目。下载地址:NSBoom.zip

【问题讨论】:

    标签: iphone core-data nsfetchedresultscontroller


    【解决方案1】:

    跟踪应用程序,我注意到首先调用了 didChangeSection,它插入了整个部分 - 然后重复调用了 didChangeObject。

    问题在于,在 didChangeSection 中插入了整个部分,然后在更新表格视图之前,您正在将对象添加到同一部分。这基本上是重叠更新的情况......(即使在开始/结束更新块中也不允许)。

    如果您注释掉单个对象插入,一切正常:

     case NSFetchedResultsChangeInsert:
                [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                 withRowAnimation:UITableViewRowAnimationFade];
                break;
    

    如果您注释掉部分插入:,它不起作用 - 但我一直不太幸运 insertRowsInSections 工作,这很可能是因为还没有部分(我确定这是为什么您要插入开头的部分)。您可能必须检测任何一种情况才能以正确的粒度进行插入。

    总的来说,我在重新加载和插入整个部分时比行更幸运,表格视图对我来说似乎非常繁琐。你也可以试试 UITableViewRowAnimationNone 似乎更频繁地运行成功。

    【讨论】:

    • 谢谢!这种观察(双重更新)让我想出了一个我可以使用的解决方法。
    【解决方案2】:

    我也有同样的问题。我发现 didChangeSection 触发了两次。一次是在您为插入创建对象时,一次是在您实际保存它时。对我来说,在调用 save 之前它不应该调用 didChangeSection。或者至少,将在创建对象时调用 willChangeSection,并在保存对象时调用 didChangeSection。

    现在我正在研究 NSManagedObjectContextDidSaveNotification 观察者方法。这不是 NSFetchedResultsControllerDelegate 协议的一部分,但您可以注册接收它。也许只有在我真正调用 save 时才会调用它,而不是之前。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-03
      • 2011-06-01
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多