0

我有一个核心数据应用程序,它具有文章数据结构&评论(一对多关系)。在NSOperation中设置核心数据关系... NSManagedObject已经失效

NSOperations管理不同线程上的下载和JSON解析,然后它使用mergeChangesFromContextDidSaveNotification将更改传递到保存它的主线程,并且fetchedResultsController负责处理tableView更改。

这些文章和评论的调用是在从服务器调用的单独的API中进行的,每个API都有它自己的NSOperation来处理导入。 (它们基于Apple的RSSImporter类松散地构建,但已经针对JSON进行了修改)。每个操作都有自己的上下文,并使用fetchedResultsController中的storeCoordinator。

commentParser.articleObjectID = [article objectID]; 
commentParser.persistentStoreCoordinator = [[self.fetchedResultsController managedObjectContext] persistentStoreCoordinator]; 

我正在尝试设置物品之间,并在的NSOperation关系的意见,我相信我通过将物品进入评论操作的objectID,然后使用该对象以下的最佳实践通过执行以下操作:

Article *article = (Article *)[self.insertionContext objectWithID:articleObjectID]; 
Comment *aComment = (Comment *)[NSEntityDescription insertNewObjectForEntityForName:@"Comment" inManagedObjectContext:self.insertionContext]; 
[aComment setCommentArticle:article]; 

这似乎很好地工作,但要回根的viewController其中原创文章的的tableView的时候,我得到了以下错误消息:

* Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'The NSManagedObject with ID:0xdb24f30 has been invalidated.'

任何帮助,将不胜感激!

回答

2

您必须在创建它们的线程(对持久性存储库)中保存新的Core Data实体(或对现有实体的更改),然后将该对象ID传递到主线程,该线程上的NSManagedContext将使用该主线程objectID从持久性存储中检索对象。

已经看清楚了: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html

所以一定要保存你在后台线程创建的新对象(或改变对象)到的NSManagedObjectContext,然后一切都应该正常工作。

+0

嗨达米安。谢谢回复!我在操作结束时保存了insertionContext(后台线程moc),它将通知中的对象传递回主线程,然后合并上下文。所以不要使用对象本身。我将objectID传递回主线程并重新获取? – 2011-04-13 15:37:51

+0

通常我会在mergeChangesFromContextDidSaveNotification中处理它。您可以发布保存操作以及您的问题如何融入您的问题,并且能够提供更有针对性的帮助? – Damien 2011-04-13 15:47:33

+0

你的问题触发*关注*为我的部分是:NSOperations管理在不同的线程下载和JSON解析然后使用mergeChangesFromContextDidSaveNotification通过在那里的将更改保存到主线程和fetchedResultsController需要的的tableView变化照顾。 – Damien 2011-04-13 15:48:07

2

达米恩让你走上正轨。下面是如何处理这个:

  1. 在你的主线程的对象被注册为NSManagedObjectContextDidSaveNotification

  2. NSOperation下载JSON并将其添加到操作中初始化的管理对象上下文,保存上下文时所有对象都被添加了。

  3. 当发生NSManagedObjectContextDidSaveNotification通知时,请确保您正在主线程上处理它。如果不是,则将消息转发到主线程上的self。 (有关示例,请参阅Apple的示例代码TopSongs)。

  4. 在主线程上处理NSManagedObjectContextDidSaveNotification时,请致电[context mergeChangesFromContextDidSaveNotification:notification]

  5. 你的NSFetchedResultsController将发送适当的协议消息给它的委托,所以你可以更新你的用户界面。

  6. 如果您需要任何其他方式您的应用程序,通知的对象,你可以发布你的对象可以观察到,做任何他们需要做一个应用程序特定的通知。

你应该从您的NSOperation传递对象ID回主线程,并重新插入上下文。你已经在NSOperation中做到了。如果您需要知道主线程上的新对象标识可以通过并使用它们,但对象已被插入并保存到您的上下文中。

+0

Hi XJones。这是我目前的保存方法http://pastie.org/1791643 – 2011-04-13 16:06:36

+0

只是想我会补充说,操作中保存的对象确实出现在我已经NSLog'd的数组中。 – 2011-04-13 16:12:00

+0

+1不通过ObjectId的回 – Damien 2011-04-13 16:12:31

0

一件事来检查:直到对象被保存到店

ManagedObjectIDs只是暂时的ID。因此,如果您在保存对象之前取得新创建的对象的ID并将其交给另一个线程/操作,那么它将只有一个临时ID,当对象实际上由任何线程/操作保存时它将会改变。

我不知道从阅读说明书,但它可能是你正在努力寻找一个临时的ID不再有效的对象。

+0

感谢您的回复。我认为这可能是问题,所以我把一个BOOL来检查objectID是否是临时ID,但它是否返回永久ID。 – 2011-04-14 10:26:49