多线程核心数据 - NSManagedObject失效

时间:2011-07-26 15:08:20

标签: ios core-data nsmanagedobject nsmanagedobjectcontext invalidation

正如标题所示,我正在使用核心数据应用程序,该应用程序在不同的后台线程中填充对象(XML解析)

在我的后台主题中,我正在做这个

managedContext = [[NSManagedObjectContext alloc] init];
[managedContext setUndoManager:nil];

[managedContext setPersistentStoreCoordinator: [[DataManager sharedManager] persistentStoreCoordinator]];

 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
 [nc addObserver:self
        selector:@selector(mergeChanges:)
            name:NSManagedObjectContextDidSaveNotification
          object:managedContext];


NSMutableArray *returnSource = [[self parseDocument:doc] retain];


 [managedContext save:&error];

 if (error) {
     NSLog(@"saving error in datafeed"); 
 }

 [managedContext reset];

[self performSelectorOnMainThread:@selector(parseCompleteWithSource:) withObject:returnSource waitUntilDone:YES];

Merge方法如下所示:

NSManagedObjectContext *mainContext = [[DataManager sharedManager] managedObjectContext];

// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                              withObject:notification
                           waitUntilDone:YES];  

[[NSNotificationCenter defaultCenter] removeObserver:self];

我认为合并是成功的但是因为我想在UITableView中显示它总是告诉我我的对象是无效的,这是因为

[managedContext reset];

我想要做的是显示当前在数据库中的项目,在后台解析xml,如果完成,我想用新的/更新的对象更新UITableView。如何做到这一点,我可以以某种方式将对象“更新”到另一个上下文,还是合并无法正常工作?

我是否需要在Main ObjectContext中定义特定内容? 我没有运气就试过了不同的合并政策。

希望你能帮助我,谢谢!

2 个答案:

答案 0 :(得分:3)

我相信你的问题是returnSource数组的内容。如果那是一堆NSManagedObject个实例,那么它们将由后台线程上下文在后台线程上创建。

您致电-[NSManagedObjectContext reset]会使他们失效,因为这是您明确告诉上下文要做的事情。但这不是大问题。

然后继续将数组发送到主线程,通过线程边界传递NSManagedObject个实例,并且在上下文之间是一个很大的禁忌。

您需要做的是:

  1. 使用NSManagedObjectID的<{1}}创建一个数组。
  2. 通过线程边界发送对象ID数组。
  3. 使用{1}从新线程上的托管对象ID重新创建一个带有NSManagedObject的数组。
  4. 我已经制作了一些核心数据助手,遵循三个的规则(第三次写东西,把它变成一般)

    最重要的是,我隐藏了为每个线程管理不同托管对象上下文,处理通知以及所有垃圾的复杂性。相反,我已经介绍了线程本地上下文的概念。基本上懒惰地创建了NSManagedObject个实例,它们会在当前线程退出时自动注册更新和清理。

    正常用例:

    NSManagedObjectContext

    完整的源代码,包括用于从apple.com解析新闻RSS并将其存储在Core Data中的示例应用程序,可在此处获取:https://github.com/jayway/CWCoreData

答案 1 :(得分:1)

在这种情况下,没有理由在后台上下文中调用reset,因为无论如何它将随后使用后台线程消失,并且在任何情况下都不会再次使用它。当您希望上下文忘记之前的步骤时,通常使用reset进行撤消管理。

这里的主要问题是您的后台线程配置为从其创建的托管对象上下文接收通知。这是毫无意义的。

相反,您需要注册tableview控制器(在前端线程上)以从后台线程上下文中接收NSManagedObjectContextDidSaveNotification。这样,当后台上下文保存时,前/主上下文将使用新数据更新自身,这将触发更新tableview。

相关问题