掌握CoreData(第15部分,多线程并发策略父级-子级用例1)

使用父子上下文解决了实际问题

托管对象上下文是用于处理托管对象的内存暂存器。我们使用多个托管对象上下文来执行两种类型的任务。

1)对于前面部分中讨论的长时间运行的任务。 在这一部分中,我们将在实际应用中执行此操作

2)在其他情况下,例如在对用户数据进行编辑时,将托管对象上下文视为一组更改即可很有用,如果应用程序不再需要它们,则可以将其丢弃。 使用子上下文使这成为可能。 在下一部分中,我们将介绍

在本教程中,您将通过使用GooglePlayViewerApp应用程序来使用多个托管对象上下文,并通过添加多个上下文以几种方式对其进行改进。

入门

该教程入门项目是一个Google Play查看器应用程序,用于演示。当应用程序首次启动时,您将重定向到登录屏幕,如图1所示。单击Export时,会将47472 google play应用程序数据加载到Core Data中。

点击“登录”按钮后,它将重定向到列表屏幕,其中将显示所有应用程序名称,如图2所示。

项目结构

在图3中显示了项目结构的屏幕截图

ViewController →负责登录屏幕任务。 它具有点击导出和登录按钮的操作方法。 点击登录按钮时,它将重定向到列表屏幕。 点击导出按钮,它将把csv文件中的数据加载到核心数据中,并将其保存到持久性存储中。

googleplaystore.csv→包含所有Google Play应用信息,总计47472 ,如图4所示。

GooglePlayListViewController →负责显示来自Google Play应用的列表。 它从核心数据中获取数据并在表格视图中显示。

AppDelegate→负责创建Core数据堆栈。

GooglePlayViewerApp.xcdatamodeld→包含Google play实体架构和配置

转到GooglePlayViewerApp.xcdatamodeld →选择Google Play实体,如图5所示,包含Google Play csv数据所需的所有属性

观察/问题

确保首先删除该应用程序。 运行该应用程序,将出现登录屏幕。 点击文本框并开始输入,它可以正常工作。 现在,点击导航栏左上方的导出按钮,立即再次开始键入,您将看到UI挂起。
导出操作需要几秒钟,并且会阻止UI响应诸如键入之类的交互事件。

怎么了

如图7所示,由于此应用程序仅使用一个托管对象上下文 ,该上下文将csv数据填充到主线程上的Core Data中。 当您点击“导出”按钮时,将发生以下情况

  1. 将包含47472数据的csv文件的所有内容加载到主线程的data变量中
  2. 获取在主线程上创建的托管对象上下文引用
  3. 在主上下文上创建了GooglePlay CoreData实体,并填充其属性
  4. 将数据推送到持久性存储

正如您在图7控制台日志中看到的那样,大约6秒的应用程序主线程将被此任务阻塞,您可以想象当应用程序冻结将近6秒时,用户的反应是什么

使用并发提高性能

如您所见,我们将主线程的阻塞时间从6秒减少到0.5秒。 如您在图8中看到的,我们做了很多事情

  1. 我们在上一部分中了解到创建的父子配置,其中父是主线程托管对象上下文,当您点击登录时,该对象正在填充列表屏幕。 仅与UI相关的任务交互是责任
  2. 在子上下文上调用perform :方法可切换创建该线程的线程。 注意:不要调用performAndWait :因为它会串行运行并且还会使主线程空闲。
  3. 从CSV加载内容和创建Core Data对象是在Private Queue /线程上完成的,Core Data对象的上下文是私有的子上下文
  4. 经过繁重的处理后,我们合并了主线程上下文(父级)上的更改。 合并将在主线程上完成 在这0.5秒的时间内,主线程将处于繁忙状态。

通过使用父子并发策略,我们可以获得巨大的性能提升。

摘要

如前所述,我们使用多个托管对象上下文来执行两种类型的任务。 一项任务是将长时间运行的任务移至某个后台线程。 在这一部分中,我们使用父子配置来实现
对于长时间运行的任务(实现并发)

接下来是什么?

在下一部分中,我们将研究如何使用父子配置来解决上下文中发生的临时更改问题

有用的链接

https://code.tutsplus.com/tutorials/core-data-from-scratch-concurrency–cms-22131

https://www.raywenderlich.com/7586-multiple-managed-object-contexts-with-core-data-tutorial