如何将NSManagedObject从一个上下文复制或移动到另一个上下文?

我有我认为是一个相当标准的设置,一个暂时保存从未保存(包含从网上下载的一堆对象)和另一个持久对象的永久MOC暂停MOC。 当用户从scratchMOC中select一个对象添加到她的库中时,我想要1)从scratchMOC中移除该对象并插入到permanentMOC中,或者2)将该对象复制到permanentMOC中。 核心数据常见问题说我可以像这样复制一个对象:

NSManagedObjectID *objectID = [managedObject objectID]; NSManagedObject *copy = [context2 objectWithID:objectID]; 

(在这种情况下,context2将是permanentMOC。)但是,当我这样做时,复制的对象是故障的; 数据最初是未解决的。 当它得到解决后,所有的值都是零; 来自原始managedObject的数据(属性或关系)都没有被实际复制或引用。 因此,我看不出使用这个objectWithID:方法之间的任何区别,只是插入一个全新的对象到永久MOC使用insertNewObjectForEntityForName :.

我意识到我可以在permanentMOC中创build一个新对象,并手动复制旧对象中的每个键值对,但是我对这个解决scheme并不满意。 (我有一些不同的pipe理对象,我有这个问题,所以我不想写和更新副本:所有的方法,因为我继续开发。)有没有更好的办法?

首先,在单个线程上拥有多个NSManagedObjectContext 不是标准configuration。 99%的时间你只需要一个上下文,这将为你解决这种情况。

为什么你觉得你需要多个NSManagedObjectContext

更新

这实际上是我所看到的有用的案例之一。 要做到这一点,你需要做一个对象的recursion副本从一个上下文到另一个。 工作stream程如下:

  1. 在持久性上下文中创build新对象
  2. 获取源对象的属性字典(使用-dictionaryWithValuesForKeys-[NSEntityDescription attributesByName]来执行此操作。
  3. 将值字典设置到目标对象上(使用-setValuesForKeysWithDictionary
  4. 如果你有关系,你将需要recursion地执行这个拷贝,并且通过硬编码(避免一些循环逻辑)或者通过使用-[NSEntityDescription relationshipsByName]

正如另一个提到的,你可以从我的书“实用程序员核心数据手册”下载示例代码,并看到这个问题的一个解决scheme。 当然在这本书中,我会深入讨论它:)

该文件是误导和不完整的。 objectID方法本身不复制对象,它们只是保证你已经得到了你想要的特定对象。

示例中的context2实际上是源上下文,而不是目标。 你得到一个零,因为目标上下文没有对象与该ID。

由于对象图的复杂性和上下文pipe理图的方式,复制pipe理对象是相当复杂的。 您必须在新的上下文中重新创build复制的对象。

下面是一些示例代码 ,我从“Pragmatic Programmer's Core Data:Mac OS X上持久化数据的Apple API”的示例代码中截取 。 (您可以下载整个项目代码,而无需在Pragmatic站点购买该书)。它应该为您提供关于如何在上下文之间复制对象的粗略想法。

您可以创build一些复制对象的基本代码,但每个对象图关系的详细信息通常意味着您必须为每个数据模型进行自定义。

自己也有同样的问题,并发现这篇文章关于创build断开连接的实体,以后可以添加到上下文中: http : //locassa.com/temporary-storage-in-apples-coredata/

这个想法是你有一个NSManagedObject,因为你要存储在数据库中的对象。 我的障碍是,许多这些对象通过HTTP API下载,我想在会议结束时抛出大部分对象。 想想用户post,我只想保存那些被collections或保存为草稿的。

我使用创build所有我的post

 + (id)newPost { NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:self.managedObjectContext]; Post *post = [[Post alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:nil]; return post; } 

然后当这些post被collections时,这些post被插入到本地pipe理对象上下文中

 + (BOOL)favoritePost:(Post *)post isFavorite:(BOOL)isFavorite { // Set the post's isFavorite flag post.isFavorite = [NSNumber numberWithBool:isFavorite]; // If the post is being favorited and not yet in the local database, add it NSError *error; if (isFavorite && [self.managedObjectContext existingObjectWithID:post.objectID error:&error] == nil) { [self.managedObjectContext insertObject:post]; } // Else if the post is being un-favorited and is in the local database, delete it else if (!isFavorite && [self.managedObjectContext existingObjectWithID:post.objectID error:&error] != nil) { [self.managedObjectContext deleteObject:post]; } // If there was an error, output and return NO to indicate a failure if (error) { NSLog(@"error: %@", error); return NO; } return YES; } 

希望有所帮助。

您需要确保您保存了managedObject所在的上下文。为了在不同的上下文中获取同一个对象,它需要存在于持久性存储中。

根据文档 , objectWithID:总是返回一个对象。 所以事实上,故障parsing为一个对象的所有nil值意味着它没有在持久存储中find你的对象。