如何处理临时NSManagedObject实例?

我需要创buildNSManagedObject实例,与他们做一些东西,然后垃圾或存储到SQLite数据库。 问题是,我不能创build与NSManagedObject不连接的NSManagedObjectContext实例,这意味着我不得不以某种方式清除之后,我决定我不需要我的数据库中的一些对象。

为了处理这个问题,我使用相同的协调器创build了一个内存中的存储,我使用assignObject:toPersistentStore.将临时对象放在那里assignObject:toPersistentStore. 现在,我如何确保这些临时对象不能访问我从公共数据库中获取的数据? 还是我必须为这样的任务创build单独的上下文?


UPD:

现在我正在考虑为内存存储制作单独的上下文。 如何将对象从一个上下文移动到另一个上下文? 只要使用[上下文insertObject:]? 在这个设置中它可以正常工作吗? 如果从对象的graphics中插入一个对象,整个graphics是否也被插入到上下文中?

最简单的方法是创build没有关联的NSManagedObjectContext NSManagedObject实例。

 NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC]; NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 

那么当你想保存它:

 [myMOC insertObject:unassociatedObject]; NSError *error = nil; if (![myMoc save:&error]) { //Respond to the error } 

对于Mike Weller的回答,iOS5提供了一个更简单的select。 而是使用一个NSManagedObjectContext 子项 。 它消除了通过NSNotificationCenter蹦床的需要

创build一个子上下文:

 NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; childContext.parentContext = myMangedObjectContext; 

然后使用子上下文创build对象:

 NSManagedObject *o = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject" inManagedObjectContext:childContext]; 

这些更改仅在保存子上下文时应用。 所以放弃更改就不保存。

关系还有一个限制。 即你不能创build与其他上下文中的对象的关系。 为了解决这个问题,使用objectID来从子上下文中获取对象。 例如。

 NSManagedObjectID *mid = [myManagedObject objectID]; MyManagedObject *mySafeManagedObject = [childContext objectWithID:mid]; object.relationship=mySafeManagedObject; 

请注意,保存子上下文会将更改应用于父上下文。 保存父上下文保持更改。

请参阅wwdc 2012会话214以获取完整说明。

实现这种事情的正确方法是使用新的托pipe对象上下文。 使用相同的持久性存储创build托pipe对象上下文:

 NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease]; [tempContext setPersistentStore:[originalContext persistentStore]]; 

然后你添加新的对象,改变它们等

当需要保存时,您需要在tempContext上调用[tempContext save:…],并处理保存通知以将其合并到原始上下文中。 要放弃这些对象,只要释放这个临时的上下文,并忘记它。

因此,当您保存临时上下文时,更改将保存到存储中,您只需将这些更改返回到主上下文中:

 /* Called when the temp context is saved */ - (void)tempContextSaved:(NSNotification *)notification { /* Merge the changes into the original managed object context */ [originalContext mergeChangesFromContextDidSaveNotification:notification]; } // Here's where we do the save itself // Add the notification handler [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempContextSaved:) name:NSManagedObjectContextDidSaveNotification object:tempContext]; // Save [tempContext save:NULL]; // Remove the handler again [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:tempContext]; 

这也是您应该处理multithreading核心数据操作的方式。 每个线程一个上下文。

如果您需要从这个临时上下文访问现有的对象(添加关系等),那么您需要使用对象的ID来获得像这样的新实例:

 NSManagedObject *objectInOriginalContext = ...; NSManagedObject *objectInTemporaryContext = [tempContext objectWithID:[objectInOriginalContext objectID]]; 

如果您尝试在错误的上下文中使用NSManagedObject ,则在保存时会出现exception。

从零上下文创build临时对象工作正常,直到你真的试图与上下文!=零的对象的关系!

确保你没事吧。

你所描述的正是NSManagedObjectContext的用途。

核心数据编程指南:核心数据基础

您可以将托pipe对象上下文视为智能便笺本。 当您从持久性存储中获取对象时,可以将临时副本带到它们形成对象graphics(或对象graphics集合)的便笺本中。 然后,您可以修改这些对象,只要你喜欢。 但是,除非实际保存这些更改,否则持久性存储保持不变。

核心数据编程指南:pipe理对象validation

这也支持代表“便笺式”的pipe理对象上下文的概念 – 一般而言,您可以将pipe理对象带到便笺式屏幕上,然后根据需要对其进行编辑,然后再提交更改或丢弃它们。

NSManagedObjectContext被devise为轻量级的。 你可以随意创build和丢弃它们 – 这是一个持续性的店铺协调员,而且是“重”的依赖。 单个持久性商店协调员可以有许多与其关联的上下文。 在旧的,过时的线程约束模型下,这意味着在每个上下文中设置相同的持久存储协调器。 今天,这意味着将嵌套上下文连接到与持久性存储协调器相关联的根上下文。

创build一个上下文,在该上下文中创build和修改托pipe对象。 如果你想坚持他们,并沟通这些变化,保存上下文。 否则丢弃它。

试图独立于NSManagedObjectContext创build托pipe对象正在寻求麻烦。 请记住,Core Data最终是一个对象图的变更跟踪机制。 因此,托pipe对象实际上是托pipe对象上下文的一部分 。 上下文观察它们的生命周期 , 没有上下文,并不是所有的pipe理对象function都能正常工作。

根据您对临时对象的使用情况,上述build议有一些注意事项。 我的用例是我想创build一个临时对象并将其绑定到视图。 当用户select保存这个对象时,我想设置与现有对象的关系并保存。 我想这样做,以避免创build一个临时对象来保存这些值。 (是的,我可以等待,直到用户保存,然后抓取视图的内容,但我把这些视图内的一个表,逻辑做这个不那么优雅。)

临时对象的选项是:

1)(首选)在子上下文中创build临时对象。 这是行不通的,因为我将对象绑定到UI,我不能保证在子上下文中调用对象访问器。 (我没有发现任何其他文件,所以我必须假设。)

2)用零对象上下文创build临时对象。 这不起作用,并导致数据丢失/损坏。

我的解决scheme:我解决了这个问题,通过创build无对象上下文的临时对象,但是当我保存该对象,而不是将它插入为#2时,我将它的所有属性复制到我在主上下文中创build的新对象中。 我在我的NSManagedObject子类中创build了一个名为cloneInto的支持方法:它让我可以轻松地为任何对象复制属性和关系。

对我来说,马库斯的答案并不奏效。 以下是对我有用的东西:

 NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC]; NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 

那么,如果我决定保存它:

 [myMOC insertObject:unassociatedObjet]; NSError *error = nil; [myMoc save:&error]; //Check the error! 

我们也不能忘记释放它

 [unassociatedObject release]