核心数据:为什么必须调用重新加载数据才能使我的应用运行?

我整晚都在调试一个简单的应用程序。 该应用程序从Web中检索一个图像(是一个…以使我的生活更轻松),并在表格视图中显示它。 我这样做是为了学习核心数据。 在我修复它之前,错误消息显示如下:

2012-09-30 06:16:12.854缩略图[34862:707] CoreData:错误:严重的应用程序错误。 在调用-controllerDidChangeContent:期间,从NSFetchedResultsController的委托中捕获到exception。 无效更新:无效的节数。 更新后的表视图中包含的节数(1)必须等于更新前的表视图中包含的节数(0),加上或减去插入或删除的节数(插入0,0删除)。 with userInfo(null)

基本上它说FRC委托方法出了问题 。 一方面,节号从0变为1.另一方面,“0插入,0删除”。 那么节号如何增加? 这应该不会发生..因此错误。

我通过简单地[self.tableView reloadData]添加到我的FRC设置方法来修复错误。 我从这篇文章中得到了灵感,但我不太明白。 答案似乎过于复杂和具体项目。 有人可以解释为什么添加reloadData可以修复bug吗? 答案可能很简单,我希望如此。

我的应用程序的关键组件,如果重要:

  • 使用UIManagedDocument建立核心数据堆栈
  • 创建一个帮助方法,从Flickr API下载图像
  • 在NSManagedObject子类文件中,尝试从持久存储中获取图像。 如果还没有,请将其插入MOC。

     - (void)setupFetchedResultsController { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"BigImage" inManagedObjectContext:self.document.managedObjectContext]; [fetchRequest setEntity:entity]; NSSortDescriptor *imageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"image" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObject: imageDescriptor]; [fetchRequest setSortDescriptors:sortDescriptors]; [fetchRequest setFetchBatchSize:20]; // Create fetch results controller self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.document.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"]; self.fetchedResultsController.delegate = self; NSError *error; if (![self.fetchedResultsController performFetch:&error]) { NSLog(@"Error in performFetch: %@, %@", error, [error userInfo]); } // Critical!! I add this line to fix the bug! [self.tableView reloadData]; } 

获取的结果控制器仅跟踪第一次提取对托管对象内容的更改。 然后使用委托方法didChangeSectiondidChangeObject等将这些更改传播到表视图。

但是没有自动机制将初始提取的结果发送到表视图。 这就是你必须在performFetch之后调用reloadData的原因。

但是,有一种情况似乎会自动发挥作用。 UITableViewControllerviewWillAppear调用reloadData (如果第一次加载表)。 因此,如果您在viewDidLoad设置FRC,则会在viewWillAppear调用reloadData ,而您不必手动调用它。