Core data multithreading fetch record

问题描述 投票:3回答:1

我对CoreData中的多线程有一个疑问。如果使用多线程,则应使用单独的NSManagedObjectContext来插入新数据或进行更新,否则我们可以使用父子上下文方法。但是我仅创建新的NSManagedObjectContext。我的问题是-即使在后台线程中,我也应该使用单独的NSManagedObjectContext进行提取吗?如果不是(即我们只能使用主队列NSManagedObjectContext),那为什么我会收到__psynch_mutexwait错误?

谢谢

ios core-data nsmanagedobjectcontext
1个回答
18
投票

首先,核心数据是线程安全的。但是,您必须遵循以下规则:

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

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

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

Marcus,这是我读过的关于Core Data线程的最简洁的解释。自从引入以来就使用了它,有时候我仍然会误解这些规则!您提到“更好的解决方案”-您能详细说明吗?

我对NSManagedObjectID的使用非常不信任。在许多情况下,从一个应用程序生命周期到另一个应用程序生命周期并不相同。最初,基于文档,我们(一般为Cocoa开发人员)认为这是为我们生成的神话般的主键。事实证明这是不正确的。

在具有父/子上下文的现代开发中,环境更加令人困惑,我们需要注意一些有趣的陷阱。考虑到当前的形势,我比以前更不喜欢它。那我们用什么呢?

我们应该产生我们自己的。不需要太多。如果您的数据还没有来自服务器的主键(从基于Ruby的服务器获得id很常见),则创建一个。我喜欢称它为guid,然后有一个类似于此的-awakeFromInsert

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

[注:此代码是在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

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

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

这比-objectWithID:慢,并且应谨慎使用,并且仅在以下情况下需要使用:将对象从一个上下文反弹到另一个上下文,然后将其移动到堆栈中。

与我所做的大多数事情一样; 这不是通用解决方案

。这是一个基线,应根据每个项目进行调整。
© www.soinside.com 2019 - 2024. All rights reserved.