且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

正确实现父/子NSManagedObjectContext

更新时间:2023-01-10 10:08:18

父/子MOC模型是Core Data的一个真正强大的功能。它令人难以置信地简化了我们以前必须处理的古老的并发问题。然而,正如你所说的,并发不是你的问题。要回答您的问题:

The parent/child MOC model is a really powerful feature of Core Data. It simplifies incredibly the age-old concurrency problem we used to have to deal with. However, as you've stated, concurrency is not your issue. To answer your questions:


  1. 传统上,您使用 NSMainQueueConcurrencyType c $ c> NSManagedObjectContext 与主线程相关联,而 NSPrivateQueueConcurrencyType s用于子上下文。子上下文不需要与其父上下文匹配。如果不指定类型, NSConfinementConcurrencyType 是所有 NSManagedObjectContext 默认值。

  2. 没有看到你的代码,我的假设是你创建子上下文结束的范围,它被清理

  3. 使用父/子上下文模式时,需要使用块方法。使用块方法的最大好处是,操作系统将处理将调用的方法调用到正确的线程。您可以使用 performBlock 进行异步执行,或使用 performBlockAndWait 进行同步执行。

  1. Traditionally, you use the NSMainQueueConcurrencyType for the NSManagedObjectContext associated with the main thread, and NSPrivateQueueConcurrencyTypes for child contexts. The child context does not need to match its parent. The NSConfinementConcurrencyType is what all NSManagedObjectContexts get defaulted to if you don't specify a type. It's basically the "I will managed my own threads for Core Data" type.
  2. Without seeing your code, my assumption would be the scope within which you create the child context ends and it gets cleaned up.
  3. When using the parent/child context pattern, you need to be using the block methods. The biggest benefit of using the block methods is that the OS will handle dispatching the method calls to the correct threads. You can use performBlock for asynchronous execution, or performBlockAndWait for synchronous execution.


    您可以使用如下:

You would use this such as:

- (void)saveContexts {
    [childContext performBlock:^{
        NSError *childError = nil;
        if ([childContext save:&childError) {
            [parentContext performBlock:^{
                NSError *parentError = nil;
                if (![parentContext save:&parentError]) {
                    NSLog(@"Error saving parent");
                }
            }];
        } else {
            NSLog(@"Error saving child");
        }
    }];
}



现在,您需要记住在子上下文例如实体插入)在您保存之前不会对父上下文可用。对于子上下文,父上下文是持久存储。保存时,将这些更改传递给父级,然后父级可以将它们保存到实际的持久存储。将propogate变化保存到一级。另一方面,获取到子上下文将通过每个级别(通过父级和子级)拉取数据

Now, you need to keep in mind that changes made in the child context (e.g. Entities inserted) won't be available to the parent context until you save. To the child context, the parent context is the persistent store. When you save, you pass those changes up to the parent, who can then save them to the actual persistent store. Saves propogate changes up one level. On the other hand, fetching into a child context will pull data down through every level (through the parent and into the child)


  1. 您需要在managedObjectContext上使用某种形式的 objectWithID 。它们是在上下文之间传递对象的最安全(真的只有)的方式。正如Tom Harrington在评论中提到的,你可能想使用 existingObjectWithID:error:,因为 objectWithID:即使您传递了无效的ID(可能会导致例外)。

  1. You need to use some form of objectWithID on the managedObjectContext. They are the safest (and really only) way to pass objects around between contexts. As Tom Harrington mentioned in the comments, you may want to use existingObjectWithID:error: though because objectWithID: always returns an object, even if you pass in an invalid ID (which can lead to exceptions).