两个托管对象上下文(一个通过 setParent 与另一个嵌套:),都使用 NSMainQueueConcurrency 设置:这是明智的吗?

Posted

技术标签:

【中文标题】两个托管对象上下文(一个通过 setParent 与另一个嵌套:),都使用 NSMainQueueConcurrency 设置:这是明智的吗?【英文标题】:Two managed object contexts (one nested with the other via setParent:), both setup using NSMainQueueConcurrency: is this wise? 【发布时间】:2011-11-16 22:35:46 【问题描述】:

我在我的 ios 应用程序中使用了两个托管对象上下文。第一个上下文是第二个上下文的父上下文,利用 iOS 5 中引入的新嵌套托管上下文模型。这两个上下文都是使用 NSMainQueueConcurrencyType 创建的。

我想要实现的是一种很好的方法来处理对我的数据的临时添加和编辑,这些数据可能会或可能不会被保存,并且在主控制器对象拥有第一个上下文(父级)和子-控制器拥有第二个上下文(子)。因此,更改会冒泡,主控制器可以决定是否保存其上下文。我的上下文是嵌套的这一事实要求它们使用限制模式 (NSConfinementConcurrencyType) 进行设置。

我的问题是:我尝试实施的这种模式有缺陷吗?我刚从多篇文章中读到,大多数时候在主线程上使用多个上下文可能不是最好的主意。我也在努力确定在我的上下文中应该在哪里使用performBlockAndWait:。每次将消息发送到上下文时我是否应该使用它,即使我确定我当前正在主线程中执行?这是否包括我正在创建一个新的 NSManagedObject 的地方,如下所示:

    [theManagedObjectContext performBlockAndWait:^
    
        id *myObj = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:theManagedObjectContext];
        // more stuff done here
    ];

我对我的 NSManagedObjects 进行更改的地方呢?我还需要将它们包装在performBlockAndWait: 中吗?我使用 NSFetchedResultsController 并向其发送 performFetch 消息的地方呢?

我最好只使用一个上下文并弄清楚撤消管理器的工作原理吗?

这些新的核心数据功能的文档与我所看到的相比非常稀疏......

【问题讨论】:

【参考方案1】:

我的理解是,在向未使用限制模式初始化的 NSManagedObjectContext 发送消息时,您应该始终使用块方法 -performBlock:-performBlockAndWait:。显然,您使用哪种方法取决于您的需求。

就使用NSMainQueueConcurrencyType 初始化父子和子而言,仅当子上下文连接到 UI 时才需要这样做。如果没有,创建这个子上下文来卸载一些非必要的工作将最适合使用NSPrivateQueueConcurrencyType 的私有线程。您已经在使用基于块的方法,因此所需的更改应该是最小的。

【讨论】:

关于发送到 NSManagedObject 或 NSFetchedResultsController 实例的消息是否需要包装在 performBlock/performBlockAndWait 中的任何见解?在某些情况下,似乎上下文可能会在下面得到消息。 我只将发送到上下文的消息包装在 performBlock: 和 performBlockAndWait: 中。如果您有开发者帐户,请观看 WWDC 2011 的“Core Data 中的新功能”视频。 感谢您的建议 - 该视频的第一部分确实有助于阐明我的理解

以上是关于两个托管对象上下文(一个通过 setParent 与另一个嵌套:),都使用 NSMainQueueConcurrency 设置:这是明智的吗?的主要内容,如果未能解决你的问题,请参考以下文章

两个托管对象上下文可以共享一个持久存储协调器吗?

一个托管对象上下文的两个持久存储 - 可能吗?

核心数据单一托管对象上下文和两个线程

两个 ManagedObjectContexts 上的一个 FetchRequest

如果您想通过 Core Data 使用多个实体,您需要为每个实体提供一个托管对象上下文吗?

CoreData 通过抽象托管对象获取请求到具体托管对象