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

时间:2011-01-09 04:49:38

标签: ipad ios core-data 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”都被正确调用。基于Apple的NSFetchedResultsControllerDelegate文档“didChangeSection”应该在“didChangeObject”之前被调用,这会阻止导致崩溃的异常。

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

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

我在我的应用程序中执行相同的操作(sectionNameKeyPath中的transient属性),并且没有看到您遇到的问题。我在iOS 4.2.1上测试了这个...有一个已知的错误,你无法信任iOS 3.X中的任何FRC委托回调,你必须在controllerDidChangeContent:message中做一个完整的[tableView reloadData]。 see the FRC documentation

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