我有一个标准的拆分视图控制器,具有详细视图和表视图。按详细视图中的按钮可以使对象在表视图的排序中更改其位置。这工作正常,只要结果订购更改不会导致添加或删除部分。即一个对象可以改变它在一个部分的顺序或者从一个部分切换到另一个部分。这些订购更改正常工作没有问题。但是,如果对象试图移动到尚不存在的部分,或者是最后一个要离开某个部分的对象(因此需要移除该部分),那么应用程序会崩溃。“didChangeSection:”NSfetchedResultsController委托方法不被调用
NSFetchedResultsControllerDelegate有方法来处理在这些情况下应该调用的被添加和删除的部分。但是这些委托方法由于某种原因没有被调用。
有问题的代码是样板:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"willChangeContent");
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)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”都被正确调用。基于苹果的NSFetchedResultsControllerDelegate文档“didChangeSection”应该在“didChangeObject”之前被调用,这将防止导致崩溃的异常。
所以我想问题是我如何确保didChangeSection被调用?
在此先感谢您的帮助!
我在我的项目中遇到了非常类似的问题。 didChangeSection似乎并不会在应该调用时调用。我为sectionNameKeyPath使用“objectID.URIRepresentation”,因为我希望每个对象都在它自己的部分中。我正在iPhone 5.1模拟器中测试。我的FRC根据值排序(增加到减少),所以如果一个对象的值改变,我的部分的顺序也应该改变,但didChangeSection函数永远不会被调用。你有什么直觉为什么这可能会发生?谢谢。 – klyngbaek 2012-03-25 00:04:26
我也在为此苦苦挣扎,首先为sectionNameKeyPath指定nil。当所有的对象被删除时,我返回0的tableView的数据源方法(fetchedObjects == 0),这打破了tableView的部分数。如果您需要触发此委托方法,则应该指定某种类型的sectionNameKeyPath。现在看起来很明显,只是认为我会分享那些像我一样木头的人。 – Schoob 2012-09-04 11:05:37