“didChangeSection:”NSfetchedResultsController委托方法未被调用

我有一个标准的拆分视图控制器,具有详细视图和表视图。 按详细视图中的按钮可以使对象在表视图的排序中更改其位置。 只要生成的排序更改不会导致添加或删除节,这样就可以正常工作。 即一个对象可以改变它在一个部分中的排序或从一个部分切换到另一个部分。 这些订购更改可以正常工作 但是,如果对象试图移动到一个尚不存在的部分,或者是留下一个部分的最后一个对象(因此要求删除它的部分),则应用程序崩溃。

NSFetchedResultsControllerDelegate具有处理添加和删除的部分的方法,在这些情况下应该调用这些部分。 但是那些委托方法由于某种原因没有被调用。

有问题的代码是样板:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { NSLog(@"willChangeContent"); [self.tableView beginUpdates]; } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { NSLog(@"didChangeSection"); switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { NSLog(@"didChangeObject"); UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { NSLog(@"didChangeContent"); [self.tableView endUpdates]; [detailViewController.reminderView update]; } 

启动应用程序,然后导致最后一个对象离开节导致以下输出:

 2011-01-08 23:40:18.910 Reminders[54647:207] willChangeContent 2011-01-08 23:40:18.912 Reminders[54647:207] didChangeObject 2011-01-08 23:40:18.914 Reminders[54647:207] didChangeContent 2011-01-08 23:40:18.915 Reminders[54647:207] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1145.66/UITableView.m:825 2011-01-08 23:40:18.917 Reminders[54647:207] Serious application error. Exception was caught during Core Data change processing: Invalid update: invalid number of sections. The number of sections contained in the table view after the update (5) must be equal to the number of sections contained in the table view before the update (6), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null) 

正如您所看到的,“willChangeContent”,“didChangeObject”(移动有问题的对象)和“didChangeContent”都被正确调用。 基于Apple的NSFetchedResultsControllerDelegate文档“didChangeSection”应该在“didChangeObject”之前被调用,这会阻止导致崩溃的exception。

所以我想问题是我如何确保调用didChangeSection?

在此先感谢您的帮助!

此问题是由使用transient属性作为sectionNameKeyPath引起的。 当我在数据库中存储用于sectionNameKeyPath的属性时,问题就消失了。 当使用transient属性作为sectionNameKeyPath时,我不知道是否有办法根据NSFetchedResultsController内容更改来更新部分。 目前我正在考虑这是瞬态属性的限制。

我在我的应用程序中执行相同的操作(sectionNameKeyPath中的瞬态属性),但我没有看到您遇到的问题。 我在iOS 4.2.1上测试这个…有一个已知的错误,你不能信任iOS 3.X中的任何FRC委托回调,你必须在controllerDidChangeContent:message中做一个完整的[tableView reloadData]。 请参阅FRC文档

我已经测试过从现有的一个部分到另一个条目到一个不存在的部分以及从一个只有一行到另一个不存在部分的部分。