我在Apple的文档中找不到的简单,常见的模式:
相反,我可以找到这些替代品,其中没有一个是正确的:
当然,这不应该这么困难吗?
如果我必须编写所有代码来手动深度复制对象(通过迭代其所有字段和数据结构),为什么CoreData首先存在?这是CD内部提供的基本功能。
我到目前为止唯一的解决方案是选项2(来自苹果公司的文档),当Apple正在为那些本来就不应该保存的对象发送NSNotifications时,自定义启发式“猜测”(但Apple发送无论如何都要通知)。那是一个可怕的黑客。
编辑:澄清:
我无法弄清楚如何正确传递Apple的通知。 Apple的代码似乎将插入转换为“更新”,并将“临时对象”转换为“删除”等。我无法听取“新对象”。
答案 0 :(得分:2)
有三种常见方法可以解决这个问题。
使用与“真实”上下文相同的持久存储创建临时对象上下文,将对象添加到此临时上下文,一旦知道要保留哪些对象,从临时上下文中删除所有其他对象并保存临时上下文。保存时,可以通过观察NSManagedObjectContextDidSaveNotification通知并将其合并到“真实”上下文(ala [realContext mergeChangesFromContextDidSaveNotification:notification])来更新“真实”上下文。有关详细信息,请参阅Mike Weller的回答here。
(如果你担心I / O,你可以使用内存上下文,这有利有弊。)
使用NSDictionary而不是使用NSManagedObject。一旦知道要保留哪些对象,就实例化一个新的托管对象并调用[managedObject setValuesForKeysWithDictionary:temporaryObject]将值从临时对象复制到托管对象,然后保存“真实”上下文。如果您有需要使用NSManagedObjects和临时对象(例如,表视图)的代码,则使用键值编码(aka valueForKey:,setValue:forKeyPath :)编写该代码。
为您的实体模型添加“isTemporary”属性(默认为NO)。创建临时对象时,将isTemporary设置为YES并将对象插入“真实”上下文。一旦知道要保留哪些对象,请将其isTemporary属性更改为NO。当然,您需要定期删除这些临时对象,但这很容易做到(例如,当该任务完成时,在应用程序退出时等)。
#1和#3的优点是你的对象生活在CoreData世界中 - 例如,它们可以被查询,它们可以参与关系等。#2的优点是它轻快,特别是如果你有很多临时物品。
答案 1 :(得分:1)
似乎选项3是最佳选择。
编辑:在iOS 4上广泛使用之后,我会说“总是使用NSOperationQueue而不是performSelectorOnBackgroundThread”。如果您不知道如何使用NSOpQ,那么谷歌就可以了,但是可以用少于3行代码完成,所以使用performSel只需要很小的改动。使用iOS4的新线程调度程序,它可以更好地工作 。基于“我怎么能强迫这个?”,我想出了这个方法:
但是......这也需要Apple的文档没有提及的内容:永远不要保存对任何托管对象的引用,除了引用所有其他对象的“根”对象。
否则,Apple的“合并”会严重破坏。
另外......你可能需要手动“刺激”错误来完成这项工作;有一些关于这一点的问题(我不知道为什么Apple不会自动执行此操作 - 也许他们会这样做,但如果是这样的话,我还没有找到让这种情况发生的神奇选项。)
我认为还有其他一些警告。如果我记得它们,我会稍后编辑它。
注意:这听起来像是很多代码。是的,但是......结果比使用字典等手动复制对象的曲折例子要少得多。
一旦你有了这个设置和工作,它在概念上很容易遵循。另外......如果您完成所有上述步骤,Apple会将“大多数”NSNotifications正确化。其余看起来不正确的(例如一些删除)是“如文档中所述”。它们对我没有意义,但至少它是如何记录下来的。
答案 2 :(得分:0)
您的对象应具有一些唯一标识符,例如唯一整数ID。这来自外部核心数据,取决于您的业务逻辑。因此,当您从外部收到新对象时,您将检查Core Data中是否已存在具有此ID的对象:如果是,则编辑现有对象;如果不是,则添加新对象。