【问题标题】:NSFetchedResultsController performFetch on background threadNSFetchedResultsController performFetch 在后台线程上
【发布时间】:2011-08-01 12:31:08
【问题描述】:

我必须在后台线程上通过NSFetchedResultsController 执行提取。

我目前的解决方案是这样的:

dispatch_queue_t fetchQueue = dispatch_queue_create("backgroundfetching", NULL);

dispatch_async(fetchQueue,^{
    // 1. Create NSManagedObjectContext
    // 2. Create NSFetchRequest
    // 3. Create NSFetchedResultsController
    // 4. PerformFetch

    dispatch_async(dispatch_get_main_queue(),^{
        [[self table] reloadData];
    });
});

dispatch_release(fetchQueue);

我的第一次测试运行良好,但这是合适的方式吗?

【问题讨论】:

标签: core-data grand-central-dispatch


【解决方案1】:

由于 fetched results 控制器旨在控制定义 tableview 的数据,它属于 UI 运行的前台线程/操作。将它放在后台线程上是毫无意义的,因为您将失去首先使用它的所有优势。

我还会担心跨异步线程发送 FRC 委托消息的影响。我不确定那会有多可靠。

说了这么多,你的实现草图看起来还不错。

【讨论】:

  • 感谢您的解释。我同意你关于 FRC 代表的看法,这可能不是最好的解决方案。无论如何,您对后台大量获取有其他建议吗?
  • FRC 的主要优点是... (1) 更改跟踪 (2) 缓存和 (3) 实现 UITableViewDataSource 方法的便利性。关于 (1),如果 FRC 的受管对象上下文中的对象发生了更改,从而将根据 FRC 结果删除、添加或更改(基于 FRC 的当前获取请求),则通知 FRC 委托这些详细信息(允许您重新加载表等)。如果您的后台线程不需要这些功能中的任何一个,您可能只需执行 fetch 即可。
  • 获取结果控制器与表视图结合。提取结果控制器是一个控制器对象,用于调解对一组提取结果的访问 - 就像名字所说的那样。
  • 糟糕,应该说不是。获取的结果控制器没有与表视图结合。
【解决方案2】:

我认为这种方法存在根本性的问题,因为您在线程之间共享托管对象(您在一个线程上获取对象并在主线程上引用它们)。在实践中它会起作用,但有时会导致崩溃。因为 Apple 明确表示,跨线程共享托管对象的唯一方法是使用 objectWithID: 方法或 MOCDidSave 通知。

来自Core Data Programming Guide

您在后台线程上获取一个托管对象上下文,并且 将获取的对象的对象 ID 传递给另一个线程。在里面 第二个线程(通常是应用程序的主线程,这样你 然后可以显示结果),您使用第二个上下文进行故障排除 具有这些对象 ID 的对象(您使用 objectWithID: 实例化 对象)。

【讨论】:

  • 但是您将如何使用NSFetchedResultsController 来做到这一点?您不能将 ObjectID 发送到获取的结果控制器,或者可以吗?
  • 我相信 NSFetchedResultsController 应该在主线程中使用。我不会感到惊讶的是,它有一些内部优化,可以从 bg 线程预取数据,然后将对象传递给主线程。
  • 很遗憾,这不足以解决此处列出的性能问题。
  • 现在我想起来了,我认为您可以将 objectIDs 发送到 fetch 请求。您可以使用类似于@"self IN(%@)", objectIDs 的谓词
  • 我想你的意思是“发送到一个获取的结果控制器”。好的,但是没有保存排序和分组、sectionNameKeyPath 等的整个繁重工作......
猜你喜欢
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多