ios - NSFetchedResultsController 一致延迟更新 UITableView 单元格;插入立即起作用

标签 ios objective-c uitableview core-data nsfetchedresultscontroller

我有一个连接到 NSFetchedResultsControllerUITableView(带有自定义单元格,如果这很重要)。我的应用程序还使用推送通知。当远程通知到达时,我分两个阶段更新我的(核心)数据模型:

1) 获取标题(带有一些自定义数据)并将其存储为新的核心数据 Entity。这里我调用了 NSManagedObjectContext save()NSFetchedResultsController 获取插入并使用 NSFetchedResultsChangeType=NSFetchedResultsChangeInsert 触发它的委托(delegate)方法 didChangeObject。 tableview 立即更新。 (插入新行)

2) 通过NSURLSession下载更多与cell相关的内容,插入到上面的Entity中,再次调用save()方法NSFetchedResultsController 再次获取更新并使用 NSFetchedResultsChangeType=NSFetchedResultsChangeUpdate 触发它的委托(delegate)方法 didChangeObject。这是我调用 configureCell 方法的地方。 tableView 已更新,但持续延迟约 10 秒。

在这两个阶段(下载-上下文保存-更新 TableView )需要显示的数据已经已经被核心数据持久化了。 (例如,在我的 configureCell.. 方法中,我知道我没有将任何单元格标签设置为 nil 或类似内容。

我的 NSFetchedResultsController 委托(delegate)方法:

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

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


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.mainTableView;

switch(type) {

    case NSFetchedResultsChangeInsert:
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(MessageTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
    }
}

我在 case NSFetchedResultsChangeUpdate: 中尝试过的其他事情

  1. 尝试在上下文保存之前调用processPendingChanges
  2. 调用 reloadRowsAtIndexPaths 而不是直接调用 configureCell
  3. 尝试将 update.. 方法包装在 beginUpdatesendUpdates 中(即使我已经有一对可以完成这项工作)
  4. [tableView reloadData]
  5. numberOfRowsInSection 不为 0!
  6. NSFetchedResultsController 委托(delegate)方法仅在主线程上运行。

简而言之,所有(?)正确的委托(delegate)方法都被正确调用。然而,我在更新单元格时看到一致的 ~10 秒延迟。然而,插入几乎是瞬间发生的。有任何想法吗?

最佳答案

@Paulw11 关于 dispatch_async... 的评论让我朝着正确的方向前进。问题在于我一直在两个不同的线程中使用相同的 ManagedObjectContext 对象,即使它们不会同时访问它。一旦我在主队列上调度了我的 save 调用(在后台线程上)(通过将其包装在 dispatch_async(dispatch_get_main_queue,^{ UIUpdate code here });),延迟消失了。一种可能的解释是,在后台线程上调用 save 会导致在后台线程上调用委托(delegate)方法。

无论如何,回到解决方案 - 永远不要在多个线程之间共享相同的 ManagedObjectContext 对象。 Use parent/child context relationships如果您要在多个线程中更新核心日期。 NSFetchedResultsController 也很适合这种模式。

关于ios - NSFetchedResultsController 一致延迟更新 UITableView 单元格;插入立即起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28957936/

相关文章:

iphone - 重新加载数据时 tableView 会崩溃

ios - 设置 rowHeight 等于 UITableViewAutomaticDimension 不起作用

ios - 向上滚动表格 View 时的黑色背景

iphone - 如何设置 UITableView 部分以每 5 行单元格开始新部分

objective-c - UIWebView 段落选择样式

ios - Swift:CoreData 错误以及如何设置实体和 DataModel?

objective-c - NSArray 和 CCArray 的区别

ios - MPMoviePlayerViewController 旋转播放录制的肖像电影

javascript - 发送短信后回调到html页面

ios - 如何根据屏幕尺寸更改字体大小