核心数据多线程导入(重复对象)

hat*_*ike 13 multithreading core-data objective-c nsoperation nsmanagedobjectcontext

我有一个NSOperationQueue,它将对象导入Core Data,这是我从web api获得的.每个操作都有我的应用程序的主要managedObjectContext的私有子managedObjectContext.每个操作都会获取要导入的对象,并检查该对象是否已存在,在哪种情况下它会更新现有对象.如果该对象不存在,则创建此新对象.然后,私有子上下文的这些更改将传播到主要托管对象上下文.

这个设置对我来说非常好用,但是有一个重复的问题.

当我在两个不同的并发操作中导入相同的对象时,我得到具有完全相同数据的重复对象.(它们都检查对象是否存在,并且它们看起来不存在).我将在同一时间导入2个相同对象的原因是我经常处理"新"api调用以及"获取"api调用.由于我的设置同时具有异步性质,因此很难确保我不会尝试导入重复的对象.

所以我的问题是解决这个特定问题的最佳方法是什么?我考虑过限制导入到最大并发操作为1(由于性能,我不喜欢这样).类似地,我考虑在每次导入操作之后要求保存并尝试处理上下文的合并.另外,我之后考虑过修饰数据以偶尔清理重复数据.最后,我考虑过只处理所有获取请求的重复项.但是这些解决方案对我来说都不是很好,也许我已经看过一个简单的解决方案了.

Tom*_*mmy 5

所以问题是:

  • 上下文只是暂存器-除非并且直到您保存,否则您对它们所做的更改不会被推送到持久性存储中;
  • 您希望一个上下文了解尚未推送的对另一上下文所做的更改。

对我来说,听起来好像上下文之间的合并不是可行的-上下文不是线程安全的。因此,要使合并发生,其他上下文的线程/队列上将无其他操作。因此,您将永远无法消除在另一个上下文正在插入新对象的同时插入新对象的风险。

其他观察:

  • 从任何实际意义上讲,SQLite都不是线程安全的。
  • 因此,无论您如何发布它们,所有到持久性存储的旅行都将被序列化。

考虑到问题和SQLite的局限性,在我的应用程序中,我们采用了一个框架,其中Web调用自然按照并发NSURLConnection进行,结果的后续解析(JSON解析加上对结果的一些钓鱼)同时进行,然后进行查找-or-create步骤被引导到串行队列中。

序列化会浪费很少的处理时间,因为SQLite行程无论如何都会被序列化,并且它们是绝大多数已序列化的东西。


Jer*_*sel 3

首先在操作之间创建依赖关系。确保在其依赖项完成之前无法完成。

查看http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/instm/NSOperation/addDependency

每个操作完成后都应该调用 save。接下来,我将尝试此处建议的查找或创建方法:

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html

它将解决您的重复问题,并且可能会导致您执行更少的提取(这是昂贵且缓慢的,因此会很快耗尽电池)。

您还可以创建一个全局子上下文来处理所有导入,然后在最后合并整个庞大的内容,但这实际上取决于数据集有多大以及您的内存考虑因素。