核心数据multithreading读取logging

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

谢谢,

首先,核心数据是线程安全的。 但是你必须遵守规则:

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

您可以在线程之间传递NSManagedObjectID实例,但必须遵守规则1和2。 从你的描述我相信你违反这些规则。

我个人不build议使用NSManagedObjectID。 有更好的解决scheme。 – Marcus S. Zarra

Marcus,这是我读过的Core Data线程的最简洁的解释。 使用它,因为它的介绍,有几天我仍然得到这些规则错了! 你提到“更好的解决scheme” – 你能详细说明一下吗?

我对使用NSManagedObjectID有一个相当强烈的不信任。 在许多情况下,从一个应用程序生命周期到另一个应用程序生命周期并不一样 最初,基于文档,我们(cocoa开发人员)认为这是我们为我们创造的神话主键。 结果是不正确的。

在现代的发展与父母/孩子的情况下,景观更混乱,有一些有趣的陷阱,我们需要注意。 鉴于目前的情况,我不喜欢它比以前更多。 那么我们使用什么?

我们应该创造自己的。 它不需要太多。 如果您的数据已经没有从服务器的主键(从基于Ruby的服务器有一个id很常见),然后创build一个。 我喜欢叫它guid ,然后有一个类似这样的-awakeFromInsert

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

注意:这段代码是写在网页浏览器中的,可能无法编译。

您检查值,因为每个上下文调用一次-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 

注意:这段代码是写在网页浏览器中的,可能无法编译。

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

这比-objectWithID:-objectWithID:只有在需要将对象从一个上下文反弹到另一个上下文的情况下,应该谨慎使用。

和我所做的大部分事情一样, 这不是一个通用的解决scheme 。 这是一个基准,应该根据每个项目进行调整。