且构网

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

正确实现父/子 NSManagedObjectContext

更新时间:2023-01-10 10:21:07

父/子 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 用于与主线程关联的 NSManagedObjectContext,将 NSPrivateQueueConcurrencyType 用于子上下文.子上下文不需要与其父上下文匹配.NSConfinementConcurrencyType 是所有 NSManagedObjectContext 的默认值,如果您不指定类型.它基本上是我将为 Core Data 管理自己的线程"类型.
  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.

您可以使用它,例如:

- (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");
        }
    }];
}

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

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). For more details: Link