【问题标题】:How to avoid the UI freeze while a Managed Object Context is saving?保存托管对象上下文时如何避免 UI 冻结?
【发布时间】:2012-12-29 17:19:15
【问题描述】:

我想实现一个大型数据集的 UI 响应式下载和解析,并使用 Core Data 保存它。

我的设置:

我在自定义视图控制器中显示下载的内容。我不使用 NSFetchedResultsController。

有 3 个 MOC:

  1. masterMOC(负责保存到磁盘,NSPrivateQueueConcurrencyType)
  2. mainMOC(由 UI 使用,NSMainQueueConcurrencyType,masterMOC 的子级)
  3. backgroundMOC(负责从 JSON 导入,在单独的线程中创建,masterMOC 的子线程)

我正在批量导入 - 每 50 件商品我通过以下方式执行 MOC 保存:

NSError *error;
[backgroundMOC save:&error];
NSManagedObjectContext *masterMOC = backgroundMOC.parentContext; //set during initialization               
[masterMOC performBlock:^{
    NSError *parentContextError = nil;
    [masterMOC save:&parentContextError];
}];

我希望在保存 masterMOC 之后对 mainMOC 进行更改。如果我在 masterMOC 保存时尝试访问随机托管对象的某些关系(保存需要一些时间),UI 会挂起,直到保存完成。

问题:如何避免masterMOC保存时UI冻结?

【问题讨论】:

  • 重读你的问题:上面的sn-p代码是在主线程还是在单独的线程中执行的?
  • 我看不出使用块的好处。为什么不将backroundMOCmasterMOC 放到同一个线程中?
  • 到底是怎么回事?解析还是保存?您的数据是大还是复杂?我想最安全的路径应该是充分原子化数据以使提交足够短。
  • 我已经实现了这里描述的方法:stackoverflow.com/questions/10542097/…。我将 masterMOC 保存在一个块中,因为它是用 NSPrivateQueueConcurrencyType 初始化的

标签: ios core-data nsmanagedobjectcontext


【解决方案1】:

您的问题可能是数据存储在您写入数据时被阻塞。因此,要么使数据存储非阻塞(在您的情况下这可能或不可能),或者如果不可行,则使访问器非阻塞。在后一种情况下,GUI 不会挂起,但在访问结果返回之前它也不会更新。

【讨论】:

  • 这听起来很有希望!但是我找不到任何关于这两种情况如何完成的信息?我应该在 NSPersistentStoreCoordinator 的 addPersistentStoreWithType:configuration:URL:options:error 的配置部分中的某处设置非阻塞吗?
  • 如果我没记错的话,Core Data 中没有太多选择。例如,如果您使用 SQLite 存储,则取决于 SQLite 是否在编译时启用了线程安全,以及 Core Data 如何在内部管理对 SQLite 的访问(即线程是否共享文件描述符 = 阻塞;文件描述符每个线程 = 非阻塞)。不过,我认为不可能告诉 Core Data 使用自定义构建的 SQLite,因此您取决于 Apple 提供的内容。不过,我可能是错的。这同样适用于其他数据存储。
  • 如果是一个选项,您还可以使您一次写入存储的块更小,并仅在前一个工作完成时发出下一个提交。通过这种方式,您可以最大限度地减少冻结的 UI 时间:读取在相对较小的写入之后排队,而不是较大的写入。
  • 我尝试了后一个选项:在我为 500 个解析项目挂起约 1 分钟之前,现在有 50 个项目的块,UI 挂起约 5 秒但 10 次,所以很难说哪个方式对用户来说更烦人:)
  • 无论如何感谢您的帮助,我怎样才能实现第二个选项,即使访问器非阻塞,是否更容易?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
  • 2012-06-27
  • 1970-01-01
相关资源
最近更新 更多