NSManagedObjectContext 并发

Posted

技术标签:

【中文标题】NSManagedObjectContext 并发【英文标题】:NSManagedObjectContext concurrency 【发布时间】:2015-07-15 12:49:32 【问题描述】:

在文档中:NSManagedObjectContext Class Reference 声明:

基于队列的托管对象上下文的 Setter 方法是线程安全的。您可以直接在任何线程上调用这些方法。

谁能给出一个代码示例来说明这到底是什么意思。是否真的意味着阅读“基于队列的托管对象上的Setter方法是线程安全的”

另外,如果我有一个存储为 iVar 的托管对象(不是最佳实践),我可以调用它的 managedObjectContext 方法,然后从任何线程中安全地调用它的 performBlock() 方法吗?

【问题讨论】:

我建议你看看这篇文章。 ***.com/questions/30875917/… 太好了,这正是我要找的。再次感谢。 【参考方案1】:

不,它的意思正是它所说的。您可以从任何线程调用NSManagedObjectContext 上的setter 方法。例如:-[setParentContext:]-[setPersistentStoreCoordinator:]

您可以从任何线程调用-[performBlock:]-[performBlockAndWait:],因为它将执行上下文队列中传递的块。

【讨论】:

要添加到这个正确答案,是的,如果您愿意,可以致电 self.myManagedObject.managedObjectContext.performBlock...。这也是安全的。除了上下文被分配到的线程之外,您不能调用任何可能改变任何线程上NSManagedObject 实例状态的东西。 很酷,谢谢。从 Marcus 的其他帖子中获得了我需要的信息。【参考方案2】:

-[performBlock:]-[performBlockAndWait:] 用于您的应用避免访问托管对象上下文或来自错误调度队列的托管对象。

假设我已经使用 PrivateQueueConcurrencyType 将托管对象上下文设置为后台上下文,并且我们在主线程上运行此代码:

NSManagedObject *mo = [NSEntityDescription insertNewObjectForEntityForName:@"Address" inManagedObjectContext:backgroundContext];
mo.street = "Rue la place"
[backgroundManagedObjectContext save:&error]

这段代码违反了 Core Data 的并发模型,它使用私有队列上下文作为主线程的参数调用 -[insertNewObjectForEntityForName::]

所以我们应该将所有对 backgroundContext 的访问包装在一个传递给 performBlock: 或 performBlockAndWait: 的块中,它会在上下文的私有调度队列上执行块:

[self.backgroundManagedObjectContext performBlockAndWait:^
  NSManagedObject *mo = [NSEntityDescription insertNewObjectForEntityForName:@"Address" inManagedObjectContext:backgroundContext];
  mo.street = "Rue la place"
  [backgroundManagedObjectContext save:&error]
];

【讨论】:

很好的答案,但没有回答有关上下文中的设置器是线程安全的还是托管对象上的设置器是线程安全的问题。 是的,你是对的。我应该补充一点,只要从分配上下文的线程调用setter,它就是线程安全的。这就是为什么应该使用 performblock。 另外,context 上的设置器是线程安全的。调用 -setParentContext:-setPersistentStoreCoordinator: 对任何线程都是完全安全的。 感谢您的努力,但正如 Marcus 也指出的那样,这并不是我想要的。

以上是关于NSManagedObjectContext 并发的主要内容,如果未能解决你的问题,请参考以下文章

iOS5 NSManagedObjectContext 并发类型以及它们是如何使用的?

同一 NSManagedObjectContext 对象上的多个并发 perform() 调用

我可以在并发 GCD 队列中使用 NSManagedObjectContext 和 NSPrivateQueueConcurrencyType

取消 NSManagedObjectContext performBlock

设置 CoreData NSManagedObjectContext 线程优先级

CoreData 并发