iOS CoreData详解(五)多线程

article/2025/8/19 18:04:38

原创blog,转载请注明出处
blog.csdn.net/hello_hwc
欢迎关注我的iOS SDK详解专栏,这里有很多基础的文章
http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html


前言:很多小的App只需要一个ManagedContext在主线程就可以了,但是有时候对于CoreData的操作要耗时很久的,比如App开启的时候要载入大量数据,如果都放在主线程,毫无疑问会阻塞UI造成用户体验很差。通常的方式是,主线程一个ManagedContext处理UI相关的,后台一个线程的ManagedContext负责耗时操作的,操作完成后通知主线程。使用CoreData的并行主要有两种方式

  • Notificaiton
  • child/parent context

何时会使用到后台-简单来说就是要耗费大量时间,如果在主线程上会影响用户体验的时候。例如

  • 导入大量数据
  • 执行大量计算

CoreData与线程安全

有一点要时刻记住

CoreData不是线程安全的,对于ManagedObject以及ManagedObjectContext的访问都只能在对应的线程上进行,而不能夸线程。

有几条自己总结的规则

  • 对于多个线程,每个线程使用自己独立的ManagedContext
  • 对于线程间需要传递ManagedObject的,传递ManagedObject ID,通过objectWithID或者existingObjectWithID来获取
  • 对于持久化存储协调器(NSPersistentStoreCoordinator)来说,可以多个线程共享一个NSPersistentStoreCoordinator

ManagedObjectContext的类型

  1. NSConfinementConcurrencyType - context使用thread confinement 模式
  2. NSPrivateQueueConcurrencyType - context在私有线程上的
  3. NSMainQueueConcurrencyType - context在主线程上

并行的解决方案之Notification

简单来说,就是不同的线程使用不同的context进行操作,当一个线程的context发生变化后,利用notification来通知另一个线程Context,另一个线程调用mergeChangesFromContextDidSaveNotification来合并变化。

Notification的种类

  • NSManagedObjectContextObjectsDidChangeNotification 当Context中的变量改变时候触发。

  • NSManagedObjectContextDidSaveNotification 在一个context调用save完成以后触发。注意,这些managed object只能在当前线程使用,如果在另一个线程响应通知,要调用mergeChangesFromContextDidSaveNotification来合并变化。

  • NSManagedObjectContextWillSaveNotification。将要save。

一种比较好的iOS模式就是使用一个NSPersistentStoreCoordinator,以及两个独立的Contexts,一个context负责主线程与UI协作,一个context在后台负责耗时的处理。

为什么说这样做的效率更高?

这样做两个context共享一个持久化存储缓存,而且这么做互斥锁只需要在sqlite级别即可。设置当主线程只读的时候,都不需要锁。

举例

主线程使用的Context,

- (NSManagedObjectContext *)managedObjectContext {// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)if (_managedObjectContext != nil) {return _managedObjectContext;}NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];if (!coordinator) {return nil;}_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];[_managedObjectContext setPersistentStoreCoordinator:coordinator];return _managedObjectContext;
}

然后假设有一个BackgroundImport类是一个NSOperation的子类进行相关的后台操作,这里的子类执行是串行的。保存一个主线程属性

@interface BackgroundImport : NSOperation
@property (strong,nonatomic)NSManagedObjectContext * mainContext;
@end

保存一个私有的context

@interface BackgroundImport()
@property (strong,nonatomic)NSManagedObjectContext * privateContext;
@end

然后,在main函数里初始化,并且执行任务,这里一定要在main函数里初始化,因为main函数在创建的新线程上执行。并且注册通知合并变化

-(void)main{self.privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];[self.privateContext setPersistentStoreCoordinator:self.mainContext.persistentStoreCoordinator];[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {if (note.object == self.privateContext) {dispatch_async(dispatch_get_main_queue(), ^{[self.mainContext performBlock:^{[self.mainContext mergeChangesFromContextDidSaveNotification:note];}];});}}];//执行耗时的操作//执行完毕[self.privateContext performBlock:^{NSError * error = nil;if ([self.privateContext hasChanges]) {[self.privateContext save:&error];}}];
}

使用的Demo,注意这里并不是后台线程,只是简单介绍下在实例中的应用
http://download.csdn.net/detail/hello_hwc/8759945


并行的解决方案之child/parent context

ChildContext和ParentContext是相互独立的。只有当ChildContext中调用Save了以后,才会把这段时间来Context的变化提交到ParentContext中,ChildContext并不会直接提交到NSPersistentStoreCoordinator中, parentContext就相当于它的NSPersistentStoreCoordinator。

child/parent context的结构图如下

这其中有几点要注意

  • 通常主线程context使用NSMainQueueConcurrencyType,其他线程childContext使用NSPrivateQueueConcurrencyType.
  • child和parent的特点是要用Block进行操作,performBlock,或者performBlockAndWait,保证线程安全。这两个函数的区别是performBlock不会阻塞运行的线程,相当于异步操作,performBlockAndWait会阻塞运行线程,相当于同步操作。

举例
和上述类似,这次不需要监听变化,因为变化会自动提交到mainContext

  self.privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];[self.privateContext setParentContext:self.mainContext];//执行耗时的操作//执行完毕[self.privateContext performBlock:^{NSError * error = nil;if ([self.privateContext hasChanges]) {[self.privateContext save:&error];}}];

Demo下载链接
http://download.csdn.net/detail/hello_hwc/8759969

关于大量数据操作性能差距方面,这篇文章有详细的阐述
性能评估博客
所以,如果对性能要求很高,还是两个独立的context公用一个持久化存储协调器较好



http://chatgpt.dhexx.cn/article/pQeeJcsc.shtml

相关文章

CoreData在Xcode 8 中的使用

如需转载,请注明出处 在Xode8之前,CoreData的使用是非常方便的,先创建一个DataModel , ,然后创建NSManagedObject SubClass,都是一个界面上操作,非常方便,但是更新过Xcode 8后,CoreData的创建需要进行一…

CoreData

Core Data数据持久化是对SQLite的一个升级,它是ios集成的,在说Core Data之前,我们先说说在CoreData中使用的几个类。(1)NSManagedObjectModel(被管理的对象模型) 相当于实体,不过它包含 了实体间的关系(2)N…

Core Data详解

转载于:程序媛与程序猿 7.1. 什么是Core Data Core Data是一个Cocoa框架,用于为管理对象图提供基础实现,以及为多种文件格式的持久化提供支持。管理对象图包含的工作如撤销(undo)和重做(redo&#xff…

Coredata的版本升级

在开发的后期,可能因为完善和修复功能,需要对Coredata数据库表进行修改,这样就需要对CoreData进行版本升级。 比如你修改了DB字段以后,用户在旧版本上升级为新版本时会crash. 因为升级只升级了应用app,没有升级目录下的数据据db文…

在建好的项目中加入CoreData

这几天在做一个ios的小项目,项目中需要对数据进行基本的增删改查操作。于是就想用一把CoreData。但在创建项目初期,没有包含进CoreData。于是就在已建好的项目中加入CoreData。由于第一次用CoreData,各方面还不是很熟悉,在网上爬文…

CoreData的简单使用

简介 Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何…

数据持久化(五)之CoreData

简单的说,Core Data就是可以存储到磁盘的对象图,[...]Core Data可以帮我们做很多任务作.它可以作为软件的整个模型层。它不仅仅在磁盘上存储数据,也把我们需要的数据对象读取到内存中。 ——Marcus Zarra, Core Data Core Data是Mac OS X中Cocoa API的一部分&#…

coredata 详解

原文:Core Data Overview,感谢CocoaChina翻译组帮忙校对。 Core Data可能是OS X和iOS里面最容易被误解的框架之一了,为了帮助大家理解,我们将快速的研究Core Data,让大家对它有一个初步的了解,对于想要正确…

Core Data 详解

Core Data是一个Cocoa框架,用于为管理对象图提供基础实现,以及为多种文件格式的持久化提供支持。管理对象图包含的工作如撤销(undo)和重做(redo)、有效性检查、以及保证对象关系的完整性等。对象的持久化意…

Core Data概述

昨晚熬夜看发布会(本以为屌丝终于能买得起苹果了,谁知道。。。),因为看不了视频直播,所以就正好有空就把www.objc.io最新的一篇文章翻译了一下,同时感谢CocoaChina翻译组提供校对,以下为正文: Core Data可能…

CoreData 的使用

CoreData其实就是Apple为开发者提供的便捷数据存储方式,本质是对sqlite数据库的操作,操作的数据量为中到大量。 操作数据库,还有FMDB第三方库,相比于FMDB,CoreData要更简单,更方便。 集成CoreData: 1,创…

Core Data的使用

初步看了一下Core Data这个东西,本想早一点写这篇东西的,不过各种俗事缠身,又觉得自己对于Core Data机制了解的还不够深,动笔就慢了几天。不过今天盘点一下,觉得可以说一点东西出来就先说一点吧。 Core Data到底是个什…

CoreData简单使用

苹果的CoreData框架(不限于)提供了一种数据持久化解决方案,它基于如下结构(图片来源苹果官网): 其中涉及了几个概念: NSManagedObject: 数据库中一条记录在内存的实例。 NSManagedObjectConte…

ios中的coredata的使用

Core Data数据持久化是对SQLite的一个升级,它是ios集成的,在说Core Data之前,我们先说说在CoreData中使用的几个类。 (1)NSManagedObjectModel(被管理的对象模型) 相当于实体,不过它包含 了实体间的关系 (2…

CoreData使用

一、CoreData的简单使用 1.什么是CoreData 先认识一下这几个类 (1)NSManagedObjectContext(被管理的数据上下文) 作用:用来管理所有表的操作,对表的实体对应的数据库中的表的操作(插入,查询,修改…

iOS CoreData的使用

CoreData是一个专门管理数据服务的框架,把OC对象和存储在SQLite文件中的数据进行互相转换,极大地方便了开发者在数据服务方面的开发。 1. 创建CoreData 在文件创建区下,选择【Core Data】下的【Data Model】 输入CoreData的文件名Model.x…

Core Data 概述

Core Data 概述 转载自: http://www.cocoachina.com/newbie/basic/2013/0911/6981.html Core Data可能是OS X和iOS里面最容易被误解的框架之一了,为了帮助大家理解,我们将快速的研究Core Data,让大家对它有一个初步的了解&#x…

CoreData相关01 基础及运用:添加、查询、过滤、排序、分页

CoreData CoreData中几乎不用写数据库操作语句就能完成数据的本地化存储。 CoreData和iOS中的模型对象相联系在一起,只需要操作模型对象的增删改查就可以完成数据的增删改查,不用写SQL语句。 CoreData的存储方式 SQLite NSSQLiteStoreType XML NSXML…

JVM原理分析

JVM原理分析 为什么Java是一种跨平台语言 1、不同系统的JDK下载 JDK里面有:Jre和Jvm,其中就有JVM指令集的不同 JVM主要结构: 栈、堆、方法区、程序计数器、本地方法栈 mian方法的执行 通过类装载子系统进入JVM 其中栈中存放线程 来一个…