NSFetchedResultsController didChangeObject带有过滤NSPredicate

时间:2013-09-11 17:57:00

标签: ios objective-c uitableview core-data nsfetchedresultscontroller

我有一个由NSFetchedResultsController支持的UITableView,它显示了用户已添加书签的项目。可以从行内的按钮取消标记项目,这会导致问题。在项目未加书签后,它应该从表格视图中消失,因为它不再与谓词匹配,但由于更新后每个部分的行计数已被更改,我得到此错误的变体:

  

CoreData:错误:严重的应用程序错误。在调用-controllerDidChangeContent:期间,从委托NSFetchedResultsController捕获到异常。无效更新:无效   第0节中的行数。更新后现有部分中包含的行数(3)   必须等于更新前的该部分中包含的行数(4),加上或减去   从该部分插入或删除的行数(0插入,0删除)和加或减   移入或移出该部分的行数(0移入,0移出)。 with userInfo(null)

这是我非常简单的didChangeObject方法:

-(void)controller:(NSFetchedResultsController *)controller
  didChangeObject:(id)anObject
     atIndexPath:(NSIndexPath *)indexPath
   forChangeType:(NSFetchedResultsChangeType)type
    newIndexPath:(NSIndexPath *)newIndexPath
{

[super controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

}

是否有某种方法可以指示NSFetchedResultsController不会出现不匹配的计数?或者我是否完全需要一种不同的方法?

2 个答案:

答案 0 :(得分:8)

您的didChangeObject委托方法看起来非常不完整, 特别是它不会检查发生了哪个事件(插入,删除或更新)。

您可以在NSFetchedResultsControllerDelegate协议中找到模板 documenation。 该方法看起来通常类似于:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeUpdate:
            [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

您还应该实施controller:didChangeSection:atIndex:forChangeType: 委托方法。

我不明白是什么

[super controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];

致电是为了!

答案 1 :(得分:2)

Martin R给出了一个很好的答案,但他省略了一件重要的事情:

如果FetchControllerProtocol想要同时刷新很多行,它可能会崩溃。

The Apple Doc给出了一个非常清晰的过程典型示例。通过beginUpdates& amp;周围环绕您的桌子更改非常重要。 endUpdates方法。

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

如果您有部分

,您还应该实施部分刷新
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
    atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                            withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

希望这有帮助