当 didChangeObject 被调用 NSFetchedResultsController 时,UITableView 没有更新

Posted

技术标签:

【中文标题】当 didChangeObject 被调用 NSFetchedResultsController 时,UITableView 没有更新【英文标题】:UITableView isn't updating when didChangeObject is called NSFetchedResultsController 【发布时间】:2013-10-10 21:31:01 【问题描述】:

我在 UITableView 中使用 NSFetchedResultsController。我成功地收到了对- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath 的委托调用,但是我对 UITableView 中的插入/更新/删除行所做的任何更改都没有真正显示出来。我什至只是尝试在 UITableView 上设置背景颜色以查看是否会显示任何更改,但除非我推送新的视图控制器然后弹回,否则它们不会显示。然后我会看到背景颜色和表格更新。

我对 didChangeObject: 方法的实现实际上只是样板模板:

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


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


- (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:UITableViewRowAnimationFade];
            tableView.backgroundColor = [UIColor redColor];
            break;

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

        case NSFetchedResultsChangeUpdate:
            [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
            tableView.backgroundColor = [UIColor blueColor];
            break;

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

我在导航栏中添加了一个带有 IBAction 的按钮,它只调用 [self.tableView reloadData];,每当我点击它时,所有的插入和更新都会显示在表格中。但是,它们不会在更改发生时显示出来。

怎么了?

【问题讨论】:

你能确认cellForRowAtIndexPath没有被调用吗? cellForRowAtIndexPath 在更新期间被调用,但这些更新实际上并未显示在 UI 中。在插入过程中,cellForRowAtIndexPath 也会被调用,但这些行永远不会出现在 UI 中。 奇怪,你的cellForRowAtIndexPath 长什么样子? 发现问题,查看下方答案。 【参考方案1】:

看起来对 didChangeObject(和其他方法)的委托调用并未在主线程上发生,这意味着它们无法更新 UI,但这些更改只是默默地被删除了。

我更新了上面包含的三个方法,以便这些方法的主体都在主线程上分派,并且一切都按预期工作。下面是一个例子:

dispatch_sync(dispatch_get_main_queue(), ^
        [self.tableView beginUpdates];
);

【讨论】:

您不必在单独的线程中执行此操作,请检查 raywenderlich 实现:raywenderlich.com/999/… 这里可能存在更大的问题,您应该确保对上下文的更改也发生在主线程上。 你有没有发现为什么这些委托调用发生在后台线程上?我在后台有一个子上下文,当它保存时,它会导致这些调用在后台发生。我希望子上下文在保存时将更改推送到主上下文。 FRC 正在使用主要上下文,所以我找不到问题。

以上是关于当 didChangeObject 被调用 NSFetchedResultsController 时,UITableView 没有更新的主要内容,如果未能解决你的问题,请参考以下文章

NSFetchedResultsController 没有调用 didChangeObject

NSFetchedResultsController 并不总是为 NSFetchedResultsChangeMove 调用 didChangeObject:atIndexPath:forChange

Swift 2.0 转换问题 NSFetchedResultsController didChangeObject

NSFetchedResultsController didChangeObject indexPath 为空

带有过滤 NSPredicate 的 NSFetchedResultsController didChangeObject

带有 didChangeObject 的 NSFetchedResultsController 在表格视图中显示单元格的速度很慢