核心数据多线程获取记录

Sac*_*hin 2 core-data nsmanagedobjectcontext ios

我对coredata中的多线程有一个疑问.如果我们使用多线程,我们应该使用单独的NSManagedObjectContext来插入新数据或更新,否则我们可以使用父子上下文方法.但我只创建新的NSManagedObjectContext.我的问题是,我是否应该使用单独的NSManagedObjectContext甚至在后台线程中获取.如果不是(即我们只能使用主队列NSManagedObjectContext),那么为什么我得到__psynch_mutexwait错误.

谢谢,

Mar*_*rra 17

首先,Core Data是线程安全的.但是,您必须遵守以下规则:

  1. NSManagedObjectContext是线程绑定的.您只能在分配给它的线程上使用它. -init导致将上下文分配给它创建的线程.使用-initWithConcurrencyType:将允许您创建与其他线程/队列关联的上下文.
  2. NSManagedObject与a关联的任何一个NSManagedObjectContext都与它来自的上下文绑定到同一个线程/队列
  3. 没有第三条规则

您可以NSManagedObjectID在线程之间传递实例,但必须遵守规则1和规则2.根据您的描述,我认为您违反了这些规则.

我个人也不建议使用NSManagedObjectID.有更好的解决方案. - Marcus S. Zarra

Marcus,这是我读过的Core Data的线程最简洁的解释.自从它推出以来使用它,有几天我仍然会错误地遵守这些规则!你提到"更好的解决方案" - 你能详细说明吗?

我对使用它有相当强烈的不信任NSManagedObjectID.在许多情况下,它在一个应用程序生命周期中不会保持不变.最初,基于文档,我们(一般的Cocoa开发人员)认为这是我们为我们生成的神秘主键.结果证明这是不正确的.

在具有父母/子女背景的现代发展中,景观更加令人困惑,并且我们需要注意一些有趣的陷阱.鉴于目前的情况,我比以前更不喜欢它.那我们用什么呢?

我们应该生成自己的.它不需要太多.如果您的数据已经没有来自服务器的主键(通常id来自基于Ruby的服务器),那么创建一个.我想打电话给它guid然后有-awakeFromInsert类似的:

- (void)awakeFromInsert
{
  [super awakeFromInsert];
  if (![self primitiveValueForKey:@"guid"]) {
    [self setPrimitiveValue:[[NSProcessInfo processInfo] globallyUniqueString] forKey:@"guid"];
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:此代码是在Web浏览器中编写的,可能无法编译.

您检查该值,因为-awakeFromInsert每个上下文调用一次.然后我通常会在我的NSManagedObject实例上有一个方便的方法,类似于:

@implementation MyManagedObject

+ (MyManagedObject*)managedObjectForGUID:(NSString*)guid inManagedObjectContext:(NSManagedObjectContext*)context withError:(NSError**)error
{
  NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:[self entityName]];
  [fetch setPredicate:[NSPredicate predicateWithFormat:@"guid == %@", guid]];

  NSArray *results = [context executeFetchRequest:request error:error];
  if (!results) return nil;

  return [results lastObject];
}

@end
Run Code Online (Sandbox Code Playgroud)

注意:此代码是在Web浏览器中编写的,可能无法编译.

这使得错误处理和上下文/线程控制留给开发人员,但提供了一种方便的方法来检索当前上下文中的对象,并让我们将对象从一个上下文"反弹"到另一个上下文.

这比-objectWithID:并且应该小心使用,并且仅在需要在保存向上移动堆栈后将对象从一个上下文反弹到另一个上下文的情况下使用.

和我做的大多数事情一样; 这不是通用的解决方案.这是一个应根据每个项目进行调整的基线.

  • Marcus,这是我读过的Core Data的线程最简洁的解释.自从它推出以来使用它,有几天我仍然会错误地遵守这些规则!你提到"更好的解决方案" - 你能详细说明吗? (2认同)