【问题标题】:Why not use a privatecontext for all Core Data operations?为什么不对所有核心数据操作使用私有上下文?
【发布时间】:2014-09-05 05:56:01
【问题描述】:

在我的 iPhone 应用程序中,我通过 Core Data 登录后插入了大量数据。最初我在插入数据时显示加载器,因此 UI 的阻塞不是问题,但现在我删除了加载器并通过将 managedobjectcontext 并发类型更改为 NSPrivateQueueConcurrencyType 来移动后台线程上的所有插入操作以进行一些插入将 UI 从繁重的插入工作中解脱出来。

我想知道如果我对所有操作都使用相同的上下文而不是 NSMainQueueConcurrencyType 会有什么缺点,是否推荐?

【问题讨论】:

    标签: ios objective-c multithreading core-data nsmanagedobjectcontext


    【解决方案1】:

    您应该在所有的上下文中使用NSPrivateQueueConcurrencyType。例如,NSFetchedResultsController 可以在私有队列上下文中正常工作,只要您遵守使用队列限制的所有规则(即必须通过队列执行提取以及故障等)。 There is a bug with NSFetchedResultsController caching when using private queue contexts,但缓存仅涵盖有限数量的用例。

    如果/当您使用 Core Data 中的数据来更新 UI 元素时,您仍然必须从主队列访问 UI。例如,这将是访问属性以更新标签:

    [[object managedObjectContext] performBlock:^{
        NSString *text  = [object someProperty];
        [NSOperationQueue mainQueue] addOperationWithBlock:^{
            [[self someLabel] setText:text];
        }];
    }];
    

    使用私有队列限制有很多优点。缺点是您必须包含上述代码 - 这远远超过在主队列上执行 Core Data 工作。

    【讨论】:

      【解决方案2】:

      只要涉及核心数据的所有操作都在此上下文中执行,就没有缺点。

      也许有区别,但不是真正的缺点是您必须异步执行所有数据操作。

      顺便说一句,核心数据有自己的“后台”线程,只要你用“performBlock”执行所有操作就可以了。

      What is NSManagedObjectContext's performBlock: used for?

      【讨论】:

      • 如果你触摸 UI 元素,会有一个缺点。
      【解决方案3】:

      您应该告诉我们的真正细节是您正在运行什么类型的操作。

      如果您不触摸 UI,则可以在不同的线程中执行操作。例如,假设您正在从后端导入 JSON 数据(其中很多)。没有它,应用程序可能会冻结。

      NSMainQueueConcurrencyType 创建与主调度队列相关联的上下文,从而与主线程相关联。您可以使用这样的上下文将其链接到需要在主线程上运行的对象,通常是 UI 元素。所以,例如,当您处理 NSFetchedResultsController 时,您需要它。

      无论如何,我个人的建议是在您发现瓶颈时分析应用程序并使用线程上下文。 Core Data 可能会变得相当复杂。所以尽可能保持简单。

      【讨论】:

      • 除了导入 json 数据外,我还指使用从列表和视图中的核心数据获取的普通记录(在私有上下文中移动)
      【解决方案4】:

      我想说的缺点是你可能无法使用NSManagedObjects 你在-performBlock: 之外的内部和外部使用。您必须将单个属性传输到块外才能将值传递给您的 UI 元素,因为您可能无法直接从 -performBlock: 内部触摸 UI。

      另外,NSMainQueueConcurrencyType 的上下文没有后台队列。 -performBlock: 所做的是将块排队等待在 runloop 循环中执行。因此,虽然看起来代码的执行从语句继续,但一旦块开始执行,它仍然会稍后阻塞线程。

      【讨论】:

      • “我想说的缺点是你可能不会使用你在 -performBlock: 之外获得的 NSManagedObjects。”。对于使用队列限制的任何上下文都是如此,无论是私有队列还是主队列。
      • @quellish 当然可以。但是通常会在视图控制器代码中保留对托管对象的访问权,以调解模型和 UI 元素之间的信息流。使用主队列类型的上下文,您可以轻松地做到这一点,而使用私有队列则必须四处走动。
      • 如果您使用的是NSMainQueueConcurrencyType 上下文,您仍应通过performBlock: 和performBlockAndWait: 访问该上下文。如果不这样做,可能并且会在您的应用程序中引入一些细微的错误,例如对用户事件的处理不一致。
      • @quellish 事实上,Apple 的 WWDC 2011 Session 315 指出,在主线程上,您可以直接在 NSMainQueueConcurrencyType 的那些基于块的方法之外向托管对象发送消息。这也是我的经验。如有疑问,请查看。
      • 我不怀疑。它将执行,正如我所说,它可以并且将会引入一些细微的错误。你最好明确地使用performBlock: 或performBlockAndWait:。
      猜你喜欢
      • 1970-01-01
      • 2016-08-18
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-08
      • 2010-10-20
      相关资源
      最近更新 更多