核心数据通过主线程上的dispatch_sync从后台线程调用,作为为后台线程创建NSManagedObjectContext的替代方法?

时间:2012-10-04 23:29:57

标签: cocoa-touch core-data objective-c-blocks

我有两个块通过GCD在用户定义的并发队列上同时调度。在块流中的某个时刻,它们必须访问同一组核心数据管理对象。不是通过提取显式,而是通过已经获取的具有多对多关系集的对象。

据我所知,每个块都应该有自己的上下文,然后在完成时将两个上下文合并到主线程中的上下文。

但是,我想知道创建2个上下文然后合并到第三个上下文的可行替代方法是否可以执行以下操作:

- (void)someMethodThatAppliesToAdisjointSetWithRange:(NSRange)range fromSharedObject:(NSManagedObject*)someSharedObject
{
  //  Do some stuff...

  //  Create sortDescriptors

  __block NSArray* entities = nil;
  dispatch_sync(dispatch_get_main_queue(), ^{
    entities = [[[someSharedObject valueForKey:@"sprites"] sortedArrayUsingDescriptors:sortDescriptors] retain];
    entities = [entities subarrayWithRange:range]
  });

  for(id anEntity in entities)
  {
    //  STRICTLY retrieve properties from the entities
    //  And do stuff with these, BUT DON'T modify the entities themselves.
  }

  //  Continue doing stuff that has nothing to do with the managed objects.
}

- (void)dispatchMethod
{

  dispatch_async(_concurrentQueue, ^{
    [self someMethodThatAppliesToAdisjointSetWithRange:NSMakeRange(0, floor(pageData.count/2.)) fromSharedObject:someSharedObject];
  });

  dispatch_async(_concurrentQueue, ^{
    [self someMethodThatAppliesToAdisjointSetWithRange:NSMakeRange(floor(pageData.count/2.), ceil(pageData.count/2.)) fromSharedObject:someSharedObject];
  });
}

我对上面的想法是,主线程上的调度在并发流中创建了一个同步点,因为我甚至没有自己修改托管对象,所以应该没问题。但是,在整个测试过程中的某个时刻,我得到了 核心数据“声明仍处于活动状态”不一致异常。所以现在我认为他上面的代码仍然不安全。虽然异常可能实际上是由应用程序中的其他代码引起的。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

经验答案是不可以。大概是因为对托管对象中任何关系的访问都可能发生故障,并且需要上下文隐式地获取关系中的对象。

即,

for(id anEntity in entities)
  {
    //  STRICTLY retrieve properties from the entities
    //  And do stuff with these, BUT DON'T modify the entities themselves.
  }

仍然需要访问managedObjectContext。

使用两个本地上下文而不是建议方法的相同代码不会导致“Statement is still active”异常。