【发布时间】:2015-05-11 13:11:21
【问题描述】:
我有一个连接到NSFetchedResultsController 的UITableView(带有自定义单元格,如果这很重要)。我的应用程序还使用推送通知。当远程通知到达时,我分两个阶段更新我的(核心)数据模型:
1) 获取标题(带有一些自定义数据)并将其存储为新的核心数据Entity。我在这里打电话给NSManagedObjectContext save()。 NSFetchedResultsController 拿起插入并触发它的委托方法didChangeObject 和NSFetchedResultsChangeType=NSFetchedResultsChangeInsert。表格视图会立即更新。 (插入新行)
2) 通过NSURLSession 下载更多与单元格相关的内容,将其插入上述Entity 并再次调用save() method。 NSFetchedResultsController 再次获取更新并使用 NSFetchedResultsChangeType=NSFetchedResultsChangeUpdate 触发它的委托方法 didChangeObject。这就是我调用我的configureCell 方法的地方。 tableView 已更新,但持续延迟约 10 秒。
在两个阶段(下载-上下文保存-更新表格视图),需要显示的数据已经由核心数据持久化。 (例如,在我的 configureCell.. 方法中,我知道我没有将任何单元格标签设置为 nil 或类似的。
我的NSFetchedResultsController 委托方法:
- (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: 内部尝试过的其他东西
- 尝试在上下文
save之前调用processPendingChanges - 调用
reloadRowsAtIndexPaths而不是直接调用configureCell - 尝试在
beginUpdates和endUpdates中封装更新.. 方法(即使我已经有一对应该可以完成这项工作) [tableView reloadData]-
numberOfRowsInSection不是 0! -
NSFetchedResultsController委托方法仅在主线程上运行。
简而言之,所有(?)正确的委托方法都被正确调用。然而,我在更新单元格时看到了一致的约 10 秒延迟。然而,插入几乎是瞬间发生的。有任何想法吗?
【问题讨论】:
-
在网络操作完成后,您没有显示更新表的代码,但我猜您没有在主队列上调度更新。
-
好吧,如果通过“调度”更新,您的意思是调用
save,那么不,我是从NSURLSession委托方法URLSession:downloadTask:didFinishDownloadingToURL:调用save,它不在如果我没记错的话是主线程? -
那么您正在使用您创建的后台线程上下文并保存更改?
-
不,我没有使用任何父/子上下文。在我的 AppDelegate 中只有一个上下文对象声明为
atomic,NSURLSession线程正在使用它。 -
不,我的意思是您是否将任何更新 UI 的操作(例如在 tableview 上重新加载)包装在
dispatch_async(dispatch_get_main_queue,^{ UIUpdate code here });
标签: ios objective-c uitableview core-data nsfetchedresultscontroller