CoreData实现

新建一个工程,CoreDataSample

不要点Next,我们中间还有一步,我们先看一下,下面是不是有一个user CoreData,我们先点一下

我们现在想到的是模板,我们先看一下跟以前创建的工程有什么区别

多了一个文件,叫做CoreData.xcdatamodeld,并且 在Frameworks里面多了一个框架,叫做CoreData.framework(Xcode6.2之前)

所以我们创建了基于CoreData的EmptyApplication工程,比不基于CoreData模板创建的EmptyApplication工程多了两个文件

说明了什么?

说明这两个是必须得。

就像我们使用Sqlite 3.0时我们会自己添加一个动态链接库,来引用。

这两个文件分别有什么作用?

CoreData.framework提供了API

另外一个是什么呢?我们来看一下这个文件,看到了什么?

我们看到了Entity,还有一个FETCH REQUESTS,

我们在之前的Sqlite里创建过一个Preson对象,我们叫他什么?

实体,那么Entity呢?是什么意思?

我们之前使用Sqlite的时候是不是也手动创建的Person实体对不对?

我们看整个操作界面,在整个编辑的界面中,下面是不是有一个AddEntity?

来咱们点一下

Attributes是什么意思?是不是属性。

属性在OC里叫什么?@property 对吧?他们是对应的。

那如果是对应的,Attributes对应的是什么?(对应的是类);

我们在学习Sqlite的时候,我们要创建一个属性,我们写得语法是什么样的?

是不是字段名加字段类型,那后面的Type是什么?是类型吧。

虽然他多了几个字段类型,但是他本质上在Sqlite里面认为的类型还是text,同理,因为CoreData的框架,最根本的还是Sqlite类型。

创建完以后,点击Entity,再点击导航栏Editor,讲讲Editor里所有选项的意思,是干什么用得

coreData里的一个实体对象,一定是继承于NSManagedObject的,管理对象。

下面是选择你想要管理的哪一个实体

创建完以后看工程里是不是出现了一个类?

Entity的类

我们现在去看一下这个类里包含了什么信息

他自动包含了一个属性,而且他自动的将这个类继承于NSManagedObject

我们刚才所做的是不是可视化编辑,所以xcdatamodeld//提供了可视化编辑数据库实体对象

然后我们看Appdelegate里多了什么内容

比不基于CoreData的工程多了三个属性,两个方法

@property (strong, nonatomic) UIWindow *window;

//数据管理器工具类(增删改查)

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

//数据模型器工具类

@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;

//数据连接器工具类(把上面两者链接起来)

@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

下面介绍实例方法。两个减号方法。

(void)saveContext;

保存数据管理器工具,他是不是就能将上面数据管理器里的内容直接就保存在数据库里呢?

对,就是这样。

(void)saveContext;

(通过对数据管理器工具类的保存,将数据管理器工具类内管理的对象保存到实体数据库)

下面这个

(NSURL *)applicationDocumentsDirectory;(文件夹路径)

他返回的是URL,不用管,他就是个路径

我们来看一下这个方法内部是怎么实现的

他通过管理工具类然后获得了NSDocumentDirectoyNSUserDomainMask ,通过这两个属性获得了这个程序的Doucument的路径,因为他就一个方法,不用传参数

我们再来看一下Save这个方法是怎么实现的

判断managedObjectContext不为空得时候

managedobject hasChanges (当他发生变化的时候,管理的时候发生变化,比如增删改查)

后面有个&&,也就是说,我们前面的条件满足的时候,我们将会执行后面的保存方法

managedObject save:&error(将数据管理器内管理的数据保存到实体数据库里)

假如,我们使用数据库的时候,在Doucument里没有数据库文件,是不是显得特别没意思,因为数据存在哪?不知道在哪?如果你不知道的话,NSLog(@“%@”,[NSBundle mainBundle].resourcePath);打印应用程序的安装路径。。。

//使用管理器工具类

我们用一下[self managedObjectContext];

运行一下程序,再去看一下,文件出来了。

我们刚才说过他三层关系

我们只需要使用管理工具类就行了,他会自动通过连接器去访问模型器

我们去看一下[self managedObjectContext]里的方法是怎么实现的

- (NSManagedObjectContext *)managedObjectContext

{

if (_managedObjectContext != nil) {

return _managedObjectContext;

}

//通过一个GET方法创建数据连接器工具类

//结果我们发现我们又要跳一个方法

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

if (coordinator != nil) {

_managedObjectContext = [[NSManagedObjectContext alloc] init];

[_managedObjectContext setPersistentStoreCoordinator:coordinator];

}

return _managedObjectContext;

}

// Returns the managed object model for the application.

// If the model doesn't already exist, it is created from the application's model.

- (NSManagedObjectModel *)managedObjectModel

{

if (_managedObjectModel != nil) {

return _managedObjectModel;

}

//momd 去查询xcdatamodeld的这个文件

//LessonCoreData是文件名

//然后实例化创建数据模型器工具类

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"LessonCoreData" withExtension:@"momd"];

_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

return _managedObjectModel;

}

然后我们再来看一下这个流程

首先我们创建了一个管理器,然后通过连接器去访问模型器

- (NSManagedObjectContext *)managedObjectContext

{

if (_managedObjectContext != nil) {

return _managedObjectContext;

}

//通过一个GET方法创建数据连接器工具类

//结果我们发现我们又要跳一个方法

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

//创建了之后然后判断数据连接器工具类是否为空

//如果为空那就跳过

if (coordinator != nil) {

//如果不为空,创建数据管理器工具类

_managedObjectContext = [[NSManagedObjectContext alloc] init];

//设置数据库管理器工具类的数据连接器

[_managedObjectContext setPersistentStoreCoordinator:coordinator];

}

return _managedObjectContext;

}

// Returns the managed object model for the application.

// If the model doesn't already exist, it is created from the application's model.

- (NSManagedObjectModel *)managedObjectModel

{

if (_managedObjectModel != nil) {

return _managedObjectModel;

}

//momd 去查询xcdatamodeld的这个文件

//LessonCoreData是文件名

//然后实例化创建数据模型器工具类

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"LessonCoreData" withExtension:@"momd"];

_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

return _managedObjectModel;

}

// Returns the persistent store coordinator for the application.

// If the coordinator doesn't already exist, it is created and the application's store added to it.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

{

//

if (_persistentStoreCoordinator != nil) {

return _persistentStoreCoordinator;

}

//在数据连接器工具类里创建的时什么?

//数据库真实路径(绝对路径)

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"LessonCoreData.sqlite"];

//声明

NSError *error = nil;

//他在实例化数据连接器工具类的时候

//使用了一个数据模型器工具类实例化数据连接器工具类

_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

//1.数据持久化类型,也就是StoreWithType

//他里面选择的是默认的NSSQLiteStoreType,他使用的是数据库创建的

//2.configuration(设置信息)

//3.URL,数据库的绝对路径..

//4.options(选项)配置Sqlite数据库的选项(例如数据库的升级等等)

//5.error(错误信息的赋值)

//这个过程才是真正创建数据库的过程

//如果没有数据库,那就创建数据库,如果有数据库就打开数据库,进行一个连接

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

/*

Replace this implementation with code to handle the error appropriately.

abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

Typical reasons for an error here include:

* The persistent store is not accessible;

* The schema for the persistent store is incompatible with current managed object model.

Check the error message to determine what the actual problem was.

If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

If you encounter schema incompatibility errors during development, you can reduce their frequency by:

* Simply deleting the existing store:

[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

* Performing automatic lightweight migration by passing the following dictionary as the options parameter:

@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

*/

NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

//程序中断

abort();

}

//数据库添加完成后,然后他返回的是数据库连接管理工具类

//然后我们看数据库管理器工具类里面

return _persistentStoreCoordinator;

}

管理器是自动查询模型器的,但是你要设置好连接器后才可以去查询,你得告诉他找谁吧

完成之后,数据管理器工具类就结束了

那其实在创建数据库,是在哪个过程,是在连接器那部分,先连接完成了模型器,通过模型器创建了一个数据库,所以模型只提供模型,那连接器呢,是连接模型并创建了数据库,所以连接器工具类是CoreData里非常重要的一个东西,但是我们又不用他,我们只用管理器。

我们再看如何插入数据

//创建实体描述信息对象

NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Entity" inManagedObjectContext:_managedObjectContext];

//获取数据管理器工具类帮忙创建的实例对象

Event *entv = [[Event alloc]initWithEntity:entityDescription insertIntoManagedObjectContext:_managedObjectContext];

//修改entity的属性

//修改完以后将变化后的数据管理器工具类保存一次

[self saveContext];

//获取数据管理器工具类中已经包含的对象

//1.创建请求对象...

NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Eeity"];

//2.执行请求对象...然后获取请求结果

NSArray *entites = [self.managedObjectContext executeFetchRequest:request error:nil];

//3.打印数组元素

NSLog(@"%@",entites);

//删除数组内的第一个元素

Event *ent = entites[0];

总结:

CoreData数据库框架的实现核心是持久化存储

与CoreData数据库框架的所有交互都是通过数据管理器完成的,我们只对数据管理器进行操作(增删改查)

数据管理器中得数据只是内存里面的数据,我们要对他进行保存。

总结我们基于CoreData创建的工程与不基于CoreData创建的工程有什么区别。

首先是多两个文件,第一是模型文件,用来可视化编辑用的。第二是CoreData.Framework,他提供了API供我们调用

在可视化编辑里我们添加了一个实体对象,然后我们通过Xcode这个工具完成了创建一个实体类的过程

然后我们了解到了CoreData是怎么样创建数据库文件的,是通过数据连接器然后对绝对路径的一个添加,添加他得数据类型

然后 我们完成了通过数据管理器增删改查的操作。

进行更新实体

我们如果想要对实体文件进行性修改,必须要通过一些指定的步骤来操作,不然就会崩溃

首先,我们在我们的工程左侧,选中xcdatamodeld文件,然后在上方的导航栏中有Editor选项

来看一下这个选项里都有什么内容

Canvas里面是不可点击的

Add Entity添加一个实体

Add FetchRequest添加一个查询条件

Add Configuration添加一个配置

Add Attribute添加一个属性

Add Fetched Property 添加一个获取属性

Add Relationship 添加一个存储关系

Create NSManagedObject Subclass 创建一个新的实体

Add Model Version添加一个新的模型

然后我们现在想要添加一个新的模型版本,我们选中Add Model Version

这时会有一个输入框 我们来给新的模型版本起一个名字

下面选择我们基于什么版本。

点Finish

我们新的模型创建出来以后,右侧有个选项ModelVersion

选择我们的当前model版本

然后Add Entity 添加我们新的实体文件与字段

选中我们的xcdatamodeld文件,点击导航栏中Edtior选项

选择Create NSManagedObject Subclass,创建

选择我们当前最新的xcdatamodeld文件,把我们的实体文件都选中

然后我们的model类就创建出来了。

这时候,我们运行一下,接下来会崩溃

因为我们已经更新了实体文件,

//创建数据库的配置信息

//NSMutableDictionary *options = [NSMutableDictionary dictionary];

//设置数据库连接器管理工具自动升级。

//[options setObject:@(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];

//NSMigratePersistentStoresAutomaticallyOption

//是否自动迁移

//NSInferMappingModelAutomaticallyOption

//判断映射模型是否自动选择

在AppDelegaet.m中

(NSPersistentStoreCoordinator *)persistentStoreCoordinator方法里

把if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil} error:&error])

里面的options里的nil更改为@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

在更新实体的时候如果不小心就将会使程序崩溃

有很多学员都会有好奇心,在原有的实体文件内增加字段,此行为为常规犯错区域

这个时候会有一个崩溃信息为:

The model used to open the store is incompatible with the one used to create the store

这句话的意思是我们的模型器工具类打开的一个实体文件与我们用于创建存储的文件是不兼容的

我们需要重新去更新一个实体文件

我们来总结一下CoreData里我们需要记住的一些东西

NSmanagedObjectContex (数据管理器工具类)他得作用是保存信息

通过NSPersistentStoreCoordinator(数据连接器工具类)向NSManagedObjectModel(数据模型器工具类)获取数据

NSPersistentStoreCoordinator(数据连接器工具类)是CoreData中最重要的部分,他是CoreData的心脏,但是我们几乎不需要去操作他,因为我们只需要控制数据管理器工具类NSmanagedObjectContex就可以保存我们的数据。

NSmanagedObjectContex中得数据是缓存在内存中的,我们需要通过NSmanagedObjectContex save来进行更新保存才可以达到持久化的目的。

还有就是我们在更新实体的时候,要注意的是不能在原基础上去更改字段

我们需要重新去创建一个xcdatamodeld文件后再在新的实体中去进行操作

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容