IOS核心数据异步保存

Posted

技术标签:

【中文标题】IOS核心数据异步保存【英文标题】:IOS Core Data asynchronous saving 【发布时间】:2016-07-22 08:35:34 【问题描述】:

问题陈述

我无法异步保存服务器端数据

结构

我正在使用以下结构的 NSManagedObjectContext 以从父到子的顺序:

    writerManagedObjectContext (NSPrivateQueueConcurrencyType) masterManagedObjectContext (NSMainQueueConcurrencyType) backgroundManagedObjectContext (NSPrivateQueueConcurrencyType)

代码

我正在使用以下代码来保存数据

[backgroundManagedObjectContext performBlock:^
    [backgroundManagedObjectContext save:nil];
    [masterManagedObjectContext performBlock:^ // Starts blocking UI from here
        [masterManagedObjectContext save:nil];
        [writerManagedObjectContext performBlock:^
            [writerManagedObjectContext save:nil];
        ]
    ]
]

问题

代码保存良好。 backgroundManagedObjectContext 也异步保存。但是,masterManagedObjectContextwriterManagedObjectContext 都拒绝异步保存并阻塞 UI 线程。 (我知道它阻塞了 UI 线程,因为我试图执行与 Core Data 无关的操作,它们也被阻塞了。这不是持久协调器无法访问的情况)

问题

    上述代码阻塞主线程的原因是什么? 假设我可以从任何地方调用上述代码,因为save 将在每个相应的线程/上下文中被调用,我是否正确?

任何帮助将不胜感激。

编辑

http://floriankugler.com/2013/04/29/concurrent-core-data-stack-performance-shootout/

显然冻结来自尝试传播到父 NSManagedObjectContext。这篇文章似乎回避了这样一个事实,即不可能将真正的异步保存到主要上下文中。

数据被高度链接,5MB,大约需要 40 秒才能保存到 psc。我不认为我会使用帖子中描述的并行结构,因为代码库已经很大了。如果我能利用任何策略来减少这种冻结,我将不胜感激。

【问题讨论】:

【参考方案1】:

即使backgroundManagedObjectContext 是一个私有队列上下文,它仍然会将其更改传播到masterManagedObjectContext,它是它的父级。这可能是它窒息的地方。合并子上下文中的更改仍会占用 CPU 时间,其影响在 UI 等繁忙队列中变得更加明显。

您始终可以使用 Instruments 来分析正在发生的事情。

如果您的特定用例允许,请尝试将backgroundManagedObjectContext.persistentStoreCoordinator 设置为与writerManagedObjectContext 相同的psc,而不是使其成为masterManagedObjectContext 的子代。

更好的是,使用像 MagicalRecord 这样的很棒的框架。不会使您免受此类问题的影响,但更少的代码使(可以说)更容易调试。

【讨论】:

我已经在使用嵌套 MOC,如结构所示。我的问题是尽管使用了嵌套的 MOC 结构,为什么保存不是异步的。 我意识到您在重新阅读您的帖子后使用了嵌套上下文。我会编辑我的答案。您应该避免将nil 传递给save 错误处理程序。您将希望能够对错误做出反应。尝试检查错误,看看这是否是你的主队列停滞的原因。您还提到了“服务器端”。你在使用 Core Data iCloud 同步吗? 我使用的是我自己的服务器,但老实说服务器是无关紧要的。基本上我正在解析 json 数据并将它们插入到 Core Data 中。我在做错误处理——上面的代码只是为了说明我的代码是什么样子的。 我尝试在同步期间定期暂停以查看是什么阻碍了我的主队列,我只能看到数据逐渐保存。我想我无法使用这种结构完全异步保存。考虑到在 android=( 中它是如此简单,这有点令人沮丧 是的......这就是我所怀疑的......我编辑的问题上的链接也没有得到你的回答。我可能最终会仔细选择何时保存我的主要 moc。和你讨论这个很有帮助!谢谢=)

以上是关于IOS核心数据异步保存的主要内容,如果未能解决你的问题,请参考以下文章

在核心数据中同时保存上下文在 iOS7 中不起作用

iOS Swift 3核心数据-尝试递归调用-save的致命错误:上下文中止

异步获取大量资源并将它们“异步”保存到数据库中。使用哪种好模式? (AFNetworking,核心数据)

iOS - 数据保存一次到核心数据中

iOS - 核心数据 - NSManagedObjectContext - 不确定是不是保存

ios核心数据未保存