Iphone CoreData和一对多关系的并发错误

Iphone CoreData和一对多关系的并发错误,iphone,ios,multithreading,core-data,concurrency,Iphone,Ios,Multithreading,Core Data,Concurrency,我目前正在开发一个iPhone应用程序,使用CoreData作为数据持久层。在其中一个场景中,我需要在后台处理和批量更新托管对象,以避免阻塞UI线程 接下来,我有两个不同的托管对象上下文(一个用于主线程,一个用于后台线程)。以下是分配代码(在我的应用程序委托中): //主线程的对象上下文 _managedObjectContext=[[NSManagedObjectContext alloc]init]; _managedObjectContext.persistentStoreCoordina

我目前正在开发一个iPhone应用程序,使用CoreData作为数据持久层。在其中一个场景中,我需要在后台处理和批量更新托管对象,以避免阻塞UI线程

接下来,我有两个不同的托管对象上下文(一个用于主线程,一个用于后台线程)。以下是分配代码(在我的应用程序委托中):

//主线程的对象上下文
_managedObjectContext=[[NSManagedObjectContext alloc]init];
_managedObjectContext.persistentStoreCoordinator=\u coordinator;
//背景线程的对象上下文
dispatch_group_t myGroup=dispatch_group_create();
调度组异步(
我的小组,
调度获取全局队列(调度队列优先级后台,0),
^{
_bgManagedObjectContext=[[NSManagedObjectContext alloc]init];
_bgManagedObjectContext.persistentStoreCoordinator=\u coordinator;
}
);
调度组等待(myGroup,调度时间永远);
调度发布(myGroup);
当应用程序启动时,主线程只获取要显示的对象,而后台线程从网络获取新数据并更新核心数据

我使用AFNetworking并确保所有回调都在后台线程上执行。片段:

NSURLRequest*request=[nsurlRequestRequestWithURL:webserviceURL];
AFHTTPRequestOperation*操作=
[[AFHTTPRequestOperation alloc]initWithRequest:request]自动释放];
[操作setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation*操作,id响应对象){
//获取在bg线程上创建的托管对象上下文
NSManagedObjectContext*上下文=[self-bgManagedObjectContext];
//
//剪断。。。
//获取对象,更新它们
//
}失败:无];
operation.successCallbackQueue=
调度获取全局队列(调度队列优先级后台,0);
[操作启动];
在回调代码中,我根据新对象的属性获取它们,然后更新它们。一切都是美好的,直到我开始更新相关对象

我的主要实体(
Place
)定义了一个与
关键字
(穷人的全文搜索…)的单向一对多关系,当我对
地点
重新编制索引时,我首先删除所有相关的
关键字

/`self.searchWords`是一个@dynamic属性
for(self.searchWords中的NSManagedObject*word){
//上下文仍然是后台线程的对象上下文
//我们仍然在后台线程上
[上下文删除对象:word];
}
[自动搜索词:旧搜索词];
当到达
[context deleteObject:word]
时,我遇到了一个异常:NSManagedObjectContext无法删除其他上下文中的对象

当我调试和检查变量时,我可以看到:

  • self.\u cd\u managedObjectContext
    是后台线程的对象上下文
  • word.\u cd\u managedObjectContext
    是主线程的对象上下文
我发现这完全令人困惑,我不明白为什么取回的关系最终会与不同的对象上下文关联

我最终可以在后台上下文中重新获取相关的
关键字
,然后从这里删除它,但这是唯一的解决方案吗?还是我做错了什么

我建议两件事。首先,必须在执行后台MOC的线程上创建后台MOC。使用GCD,您不能永久声明任何线程。因此,这就引出了我的第二点。不要坚持你的背景MOC。它们的制造成本很低。我怀疑你的大部分问题是由于没有保持主运行中心的同步。持久存储实际上是以任何方式实现这一点的机制


Andrew

谢谢你的建议,事实上,当我需要时,我会根据需要创建背景MOC。但是,我在问题中描述的问题仍然存在。Clément,那么您就遇到了数据库一致性问题。这在许多多线程数据库应用程序中很常见。瞧,你没有CD问题。在我的例子中,我通过在对象使用很久之后删除它们来解决这个问题。也可以通过从不保存瞬态对象来解决此问题。在CD中,这最好在单独的MOC中完成。然后在处理完瞬态对象后删除MOC。安得烈