通常情况下,CoreData 的增删改查操作都在主线程上执行,那么对数据库的操作就会影响到 UI 操作,这在操作的数据量比较小的时候,执行的速度很快,我们也不会察觉到对 UI 的影响,但是当数据量特别大的时候,再把 CoreData 的操作放到主线程中就会影响到 UI 的流畅性。自然而然地我们就会想到使用后台线程来处理大量的数据操作。

使用后台 managedObjectContext

CoreData 里使用后台更新数据最常用的方案是一个 persistentStoreCoordinator 持久化存储协调器对应两个 managedObjectContext 管理上下文,NSManagedObjectContext 在创建时,可以传入 ConcurrencyType 来指定 context 的并发类型。指定 NSMainQueueConcurrencyType 就是我们平时创建的运行在主队列的 context;指定成 NSPrivateQueueConcurrencyType 的话,context 就会运行在它所管理的一个私有队列中;另外还有 NSConfinementConcurrencyType 是适用于旧设备的并发类型,现在已经被废弃了,所以实际上只有两种并发类型。
下面是创建 backgroundContext 的代码:

NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.persistentStoreCoordinator = self.persistentStoreCoordinator;

在最新的 iOS 10 中,CoreData 栈的创建被封装在了 NSPersistentContainer 类中,用它来创建 backgroundContext 更加简单:

NSManagedObjectContext *backgroundContext = ((AppDelegate *)[UIApplication sharedApplication].delegate).persistentContainer.newBackgroundContext;

另外,后台 context 的操作得放在 performBlockperformBlockAndWait 方法里执行,performBlock 会异步的执行,不会阻塞当前的线程,而 performBlockAndWait 则会阻塞当前的线程直到方法返回才会继续向下执行。下面是一段后台插入数据的示例代码:

[self.backgroundContext performBlock:^{for (NSUInteger i = 0; i < 100000; i++) {NSString *name = [NSString stringWithFormat:@"student-%d", arc4random_uniform(9999)]; int16_t age = arc4random_uniform(10) + 10; int16_t stuId = arc4random_uniform(9999); Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.backgroundContext]; student.studentName = name; student.studentAge = age; student.studentId = stuId; } NSError *error; [self.backgroundContext save:&error]; [self.logger dealWithError:error  whenFail:@"failed to insert"  whenSuccess:@"insert success"]; }];

后台插入数据之后,还没有完,因为数据是通过后台的 context 写入到本地的持久化数据库的,所以这时候主队列的 context 是不知道本地数据变化的,所以还需要通知到主队列的 context:“数据库的内容有变化啦,看看你有没有需要合并的”。这个过程可以通过监听一条通知来实现。这个通知就是 NSManagedObjectContextDidSaveNotification,在每次调用 NSManagedObjectContextsave:方法时都会自动发送,通知中的 userInfo 中包含了修改的数据,可以通过 NSInsertedObjectsKeyNSUpdatedObjectsKeyNSDeletedObjectsKey 这三个 key 获取到。

NSManagedObjectContextDidSaveNotification-w600

收到通知之后,只需要调用 [self.mainContext mergeChangesFromContextDidSaveNotification:note] 就可以将修改的数据合并到主线程的 context

下面是示例代码:

- (void)viewDidLoad {[super viewDidLoad];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveContextSave:) name:NSManagedObjectContextDidSaveNotification object:self.backgroundContext]; } - (void)doSometingInsertingInBackground { // backgroundContext .... } - (void)receiveContextSave:(NSNotification *)note { [self.context mergeChangesFromContextDidSaveNotification:note]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }

注意:通知的 userInfo 里保存的 managedObjects 不可以直接在另一个线程的 context 中直接使用!也就是 managedObject 不是跨线程的,如果想要在别的线程操作,必须通过 objectId 在另一个 context 里再重新获得这个 object

- (void)receiveContextSave:(NSNotification *)note {[self.context mergeChangesFromContextDidSaveNotification:note];NSSet<Student *> *managedObjects = note.userInfo[NSInsertedObjectsKey]; NSManagedObjectID *studentId = managedObjects.allObjects[0].objectID; [self.context performBlock:^{ // 这是错的 // Student *wrongStudent = managedObjects.allObjects[0]; // 应该这么做 Student *student = [self.context objectWithID:studentId]; // modify student... }]; }

转载于:https://www.cnblogs.com/Free-Thinker/p/7059726.html

CoreData 从入门到精通(四)并发操作相关推荐

  1. CoreData 从入门到精通(五)CoreData 和 TableView 结合

    我们知道 CoreData 里存储的是具有相同结构的一系列数据的集合,TableView 正好是用列表来展示一系列具有相同结构的数据集合的.所以,要是 CoreData 和 TableView 能结合 ...

  2. C4D致富经典入门到精通(四)

    C4D中的Nurbs建模 C4D基础界面的介绍与常用快捷键:  C4D致富经典入门到精通(一) C4D父子关系的理解与创建参数几何体与可编辑对象: C4D致富经典入门到精通(二) C4D样条曲线创建  ...

  3. CoreData 从入门到精通(三)关联表的创建

    上篇博客中讲了 CoreData 里增删改查的使用,学到这里已经可以应对简单的数据存储需求了.但是当数据模型复杂起来时,例如你的模型类中除了要存储 CoreData 里支持的数据类型外,还有一些自定义 ...

  4. 《Python入门到精通》文件操作

    「作者主页」:士别三日wyx   此文章已录入专栏<Python入门到精通>   2021最新版Python小白教程,针对0基础小白和基础薄弱的伙伴学习 文件操作 1. 打开文件 1.1 ...

  5. python语法基础语法_Python基本语法[二],python入门到精通[四]

    在上一篇博客Python基本语法,python入门到精通[二]已经为大家简单介绍了一下python的基本语法,上一篇博客的基本语法只是一个预览版的,目的是让大家对python的基本语法有个大概的了解. ...

  6. CoreData 从入门到精通 (一) 数据模型 + CoreData 栈的创建

    概述 CoreData 是 Cocoa 平台上用来管理模型层数据和数据持久化的一个框架,说简单点,就是一个数据库存储框架.CoreData 里相关的概念比较多,而且初始化也非常繁琐,所以对初学者的学习 ...

  7. Python基本语法[二],python入门到精通[四] (转)

    写在前面 python你不去认识它,可能没什么,一旦你认识了它,你就会爱上它 回到顶部 v正文开始:Python基本语法 1.定义常量: 之所以上篇博客介绍了定义变量没有一起介绍定义常量,是因为Pyt ...

  8. redis 通过aof日志恢复_Redis从入门到精通(四、Redis的持久化和数据备份与恢复)

    本文将对Redis的两种持久化方式做详细的介绍,从配置,机制,优缺点几方面讲起 Redis持久化简介 Redis提供了两种持久化的选项,一种是快照文件(snapshotting,RDB),它会基于某个 ...

  9. Atom编辑器入门到精通(四) Atom使用进阶

    原创时间:2016-01-31 更新时间:2016-06-05 在本节中将介绍Atom提供的更高级的使用技巧,通过这些技巧将会进一步提高你的代码编写效率 代码片段(Snippets) Snippets ...

最新文章

  1. 一般将来时语法课教案_「英语语法」一般过去时用法技巧全解
  2. JSP控制流语句和运算符
  3. 控制iOS的导航栏和状态栏的样式
  4. apscheduler -定时任务
  5. c语言handler指针,typedef与指向函数的指针结合的妙用
  6. 部分手机浏览器存在将ajax请求当成广告过滤的情况,及解决方案
  7. 算法:匹配有效的括号20. Valid Parentheses
  8. 【学习笔记】用Mac自学虚幻4
  9. 第1课:郭盛华课程_零基础学Linux操作系统
  10. 第一模块-开发基础-第一章python语法
  11. 在CorelDRAW 2019创建对称绘图模式
  12. c语言数组如何把一串数字存入数组_第十七章、C语言之数组1
  13. 查看linux系统CPU和内存命令
  14. Java中统计字符个数
  15. php网络通讯,Linux_网络通讯--efax,功能说明:收发传真。 语  - phpStudy
  16. 大数据说话:怎样的程序员最抢手?
  17. SpringBoot启动发生的事件顺序
  18. Xshell7.0/Xftp7.0官方免激活下载
  19. C#+asp .NET宠物店(Product模块)
  20. 马赛克效果的滤镜实现

热门文章

  1. OC仿支付宝输入UITextField输入车牌号
  2. Codeforces 558E A Simple Task
  3. 题目1208:10进制 VS 2进制(进制转换以及大数保存问题)
  4. oracle的常用sql
  5. Java Web编程的主要组件技术——Hibernate入门
  6. NHibernate Step By Step(2)-继承映射
  7. 分享《组播技术白皮书》
  8. Ubuntu 16设置固定IP和DNS
  9. 闫智宣的开发版_Android
  10. mycncart操作使用教程 - 横幅广告