CoreData

来源:互联网 发布:2016网络写手收入排行 编辑:程序博客网 时间:2024/05/02 01:22

一、概述

Core Data框架提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite3数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,不需要编写任何SQL语句。使用此功能,要添加CoreData.framework和导入主头文件<CoreData/CoreData.h>

snip20161217_1

二、相关内容及功能

1、NSManagedObject

通过Core Data从数据库取出的对象,默认情况下都是NSManagedObject对象,NSManagedObject的工作模式有点类似于NSDictionary对象,通过键-值对来存取所有的实体属性。

(1)setValue:forKey: 存储属性值(属性名为key)

(2)valueForKey: 获取属性值(属性名为key)

 

2、NSManagedObjectContext
负责应用与数据库之间的交互,增删改查基本操作都要用到

 

3、NSManagedObjectModel
被管理的数据模型,可以添加实体及实体的属性,若新建的项目带CoreData,即为XXX.xcdatamodeld

 

4、NSPersistentStoreCoordinator
数据库的连接器,设置数据存储的名字,位置,存储方式等

 

5、NSFetchRequest
获取数据时的请求

 

6、NSEntityDescription
用来描述实体

 

31205150_9sgn

 

三、模型文件

在Core Data,需要进行映射的对象称为实体(entity),而且需要使用Core Data的模型文件来描述应用的所有实体和实体属性。

这里以Person和Card(身份证)2个实体为例子,先看看实体和实体属性之间的关联关系:

31205149_cfpc

Person中有个Card属性,Card中有个Person属性,属于一对一双向关联

 

四、使用方法

下面我们将针对Person和Card的关联关系为例来学习CoreData的使用方法:

 

1、创建CoreData工程及添加实体和属性

我们新建一个名为CoreDataTest工程,新建工程时勾选Use Core Data,则AppDelegate.h中:

 

在AppDelegate.m中(为了精简,去除了注释和没用到的方法):

不过,这里为了深入理解,我们不用AppDelegate中自动生成的一些方法和属性,我们从零开始自己写,等掌握具体用法后,你自然会知道如何用AppDelegate中自动生成的方法和属性。

建好后你会发现工程中多了CoreDataTest.xcdatamodeld,我们需要在这里添加实体(首字母大写)和实体的属性。

snip20161218_4

 

这里我们需要创建Person和Card的实体以及实体属性:

snip20161218_5

snip20161218_6

 

选中Person实体,在Person中添加card属性:

snip20161218_7

 

选中Card实体,在Card中添加person属性:

snip20161218_8

添加完成后,他们关系如下:

snip20161218_9

 

2、搭建上下文环境

其中

持久化存储库的类型(addPersistentStoreWithType:参数):

(1)NSSQLiteStoreType  SQLite数据库

(2)NSBinaryStoreType  二进制平面文件

(3)NSInMemoryStoreType 内存库,无法永久保存数据

 

ConcurrencyType可选项(initWithConcurrencyType:参数):

(1)NSConfinementConcurrencyType 这个是默认项,每个线程一个独立的Context,主要是为了兼容之前的设计。

(2)NSPrivateQueueConcurrencyType 创建一个private queue(使用GCD),这样就不会阻塞主线程。

(3)NSMainQueueConcurrencyType 创建一个main queue,使用主线程,会阻塞。

 

3、:增加数据

 

4、:删除数据

 

5、:修改数据

 

6、:查询数据

 

五、CoreData与多线程

1、Notification实现CoreData并行

CoreData中的NSManagedObjectContext在多线程中不安全,在多线程编程环境下,容易出现每个上下文数据不一致问题。如果想要多线程访问CoreData的话,最好的方法是一个线程一个NSManagedObjectContext,每个NSManagedObjectContext对象实例都可以使用同一个 NSPersistentStoreCoordinator实例,在每一个线程对应一个NSManagedObjectContext的时候,尽量一个线程只读写与其对应的context。在其完成操作的时候通知另外的线程去修改其对应的context。
CoreData里面还带有一个通知NSManagedObjectContextDidSaveNotification,主要监听NSManagedObjectContext的数据是否改变,它可以帮助我们通知修改其它的context,合并数据改变到相应context。

如下图:

270478-88de65c2bbef17de

例如,我们创建一个主队列的mainContext,主要用于UI操作。一个私有队列的backgroundContext,用于除UI之外的耗时操作,两个Context使用的同一个NSPersistentStoreCoordinator:

在上面的Demo中,创建了一个psc,并将其他Context都关联到这个psc上,这样所有的Context执行本地持久化相关的操作时,都是通过同一个psc进行操作的。并在下面添加了一个通知,这个通知是监听所有Context执行save操作后的通知,并在通知的回调方法中进行数据的合并。

 

2、parent/child context实现CoreData并行

在iOS5之后,Context可以设置parentContext,一个parentContext可以拥有多个ChildContext。在ChildContext执行save操作后,会将操作push到parentContext,由parentContext去完成真正的save操作,而ChildContext所有的改变都会被parentContext所知晓,这解决了Context手动同步数据的问题。

需要注意的是,在ChildContext调用save方法之后,此时并没有将数据写入存储区,还需要调用parentContext的save方法。因为ChildContext并不拥有psc,ChildContext也不需要设置psc,所以需要parentContext调用psc来执行真正的save操作。也就是只有拥有psc的Context执行save操作后,才是真正的执行了写入存储区的操作。

parent/child context的结构图如下:

20150528140318127

这其中有几点要注意

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

上面例子中创建一个主队列的mainContext,来完成UI相关的操作。创建私有队列的backgroundContext,处理复杂逻辑以及数据处理操作,在实际开发中可以根据需求创建多个backgroundContext。需要注意的是,在backgroundContext执行完save方法后,又在mainContext中执行了一次save方法,这步是很重要的。

 

Core Data的延迟加载

Core Data不会根据实体中的关联关系立即获取相应的关联对象,比如通过Core Data取出Person实体时,并不会立即查询相关联的Card实体;当应用真的需要使用Card时,才会查询数据库,加载Card实体的信息。

本文示例项目源码下载:
 云盘下载

 

0 0
原创粉丝点击