iOS学习笔记18-CoreData你懂的

一、CoreData介绍

CoreData是iOS5之后新出来的的一个框架, 是对SQLite进行一层封装升级后的一种数据持久化方式。
它提供了对象<-->关系映射的功能,即能够将OC对象转化为数据存储到SQLite数据库文件中,同时也能将数据库中的数据还原成OC对象。相较于SQLite,我们使用CoreData就不需要再编写任何SQL语句,再也不去纠结SQL语句怎么写了O(∩_∩)O哈~。

二、CoreData核心结构图

先来张官方的图:
这四者的关系图
  • PersistentObjectStore:存储持久对象的数据库(例如SQLite,注意CoreData也支持其他类型的数据存储,例如xml、二进制数据等)。
  • ManagedObjectModel:对象模型,对应Xcode中创建的模型文件。
  • PersistentStoreCoordinator:对象模型和实体类之间的转换协调器,用于管理不同存储对象的上下文。
  • ManagedObjectContext:对象管理上下文,负责实体对象和数据库之间的交互。
说了这么多,可能你还是懵逼的,下面是我的理解图:

我对CoreData的理解

最底层的就是PersistentObjectStore,也就是我们实际存储数据的结构;
图中的模型就是ManagedObjectModel,就是数据转化为对象的模板;
以SQLite数据库为例:

  • 读取数据库的数据时,数据库数据先进入数据解析器,根据对应的模板,生成对应的关联对象。
  • 向数据库插入数据时,对象管理器先根据实体描述创建一个空对象,对该对象进行初始化,然后经过数据解析器,根据对应的模板,转化为数据库的数据,插入数据库中。
  • 更新数据库数据时,对象管理器需要先读取数据库的数据,拿到相互关联的对象,对该对象进行修改,修改的数据通过数据解析器,转化为数据库的更新数据,对数据库更新。

这些还是要在使用中进行加深理解

三、CoreData使用

1. 添加框架

  • 添加CoreData.framework
  • #import导入头文件<CoreData/CoreData.h>

2. 数据模板和对象模型

看上面的图就知道,我们需要首先创建一个数据模板,即ManagedObjectModel

下面是创建数据模板的步骤【是图形化操作,所以都是图片】:
第一步 创建数据模板文件
第二步 点开数据模板文件,添加实体,添加属性
第三步 添加关系,可以控制是一对多还是多对多
点击style,可以查看直观的关系图
第四步 根据数据模板创建对象模型文件

点击Next,会进入一个数据模板文件的选择打钩,再点Next,会进入一个实体的选择打钩,选完点Next就会自动生成对象模型文件。


自动生成对象模型文件
  • 所有的实体类型都继承于NSManagedObject,每个NSManagedObject对象对应着数据库中一条记录。
  • 集合属性(例如数组)会自动生成访问此属性的分类方法。
  • 使用@dynamic代表具体属性实现,具体实现细节不需要开发人员关心。

3. 创建对象管理上下文

创建对象管理上下文ManagedObjectContext可以细分为:
  1. 加载模型文件
  1. 指定数据存储路径
  2. 创建对应数据类型的存储
  3. 创建管理对象上下方并指定存储
下面是实例代码:
- (NSManagedObjectContext *)createDbContext{
    //打开模型文件,参数为nil则打开包中所有模型文件并合并成一个
    NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    //创建数据解析器
    NSPersistentStoreCoordinator *storeCoordinator = 
            [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    //创建数据库保存路径
    NSString *dir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
    NSString *path = [dir stringByAppendingPathComponent:@"myDatabase.db"];
    NSURL *url = [NSURL fileURLWithPath:path];
    //添加SQLite持久存储到解析器
    NSError *error;
    [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                   configuration:nil 
                                             URL:url 
                                         options:nil 
                                           error:&error];
    
    NSManagedObjectContext *context = nil;
    if( !error ){
        //创建对象管理上下文,并设置数据解析器
        context = [[NSManagedObjectContext alloc] init];
        context.persistentStoreCoordinator = storeCoordinator;
        NSLog(@"数据库打开成功!");
    }else{
        NSLog(@"数据库打开失败!错误:%@",error.localizedDescription);
    }
    return context;
}

4. 插入数据

插入数据我们需要创建一个实体对象,并把这个对象关联上对象管理器,我们创建实体对象需要使用到NSEntityDescription(实体描述类)的类方法

下面是实现代码:
- (void)addClassTest
{
    //添加一个对象
    Classes *classes = [NSEntityDescription insertNewObjectForEntityForName:@"Classes" 
                                                     inManagedObjectContext:self.context];
    classes.c_id = 301;
    classes.c_name = @"高三(1)班";
    NSError *error;
    //保存上下文,这里需要注意,增、删、改操作完最后必须调用管理对象上下文的保存方法,否则操作不会执行。
    if (![self.context save:&error]) {
        NSLog(@"添加过程中发生错误,错误信息:%@!",error.localizedDescription);
    }
}

5. 删除数据

删除数据,只需要删除关联的对象就行了:
- (void)removeClasses:(Classes *classes){
    [self.context deleteObject:classes];
    NSError *error;
    if (![self.context save:&error]) {
        NSLog(@"删除过程中发生错误,错误信息:%@!",error.localizedDescription);
    }
}

6. 查询数据

查询数据需要处理查询结果,要用到两个类:
  • NSFetchRequest:获取数据的请求
  • NSPredicate :请求的谓词,也就是获取数据的要求
1. 查询一个对象只有唯一一个关联对象的情况

例如查找用户名为“Binger”的微博(一个微博只能属于一个用户),通过keypath查询:

- (NSArray *)getStatusByUserName:(NSString *)name{
    //创建查询请求
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Status"];
    //创建谓词,设置获取数据的条件
    request.predicate = [NSPredicate predicateWithFormat:@"user.name=%@",name];
    //执行对象管理上下文的查询方法
    NSArray *array = [self.context executeFetchRequest:request error:nil];
    return  array;
}
2. 查询一个对象有多个关联对象的情况

例如查找发送微博内容中包含“Watch”并且用户昵称为“小娜”的用户(一个用户有多条微博)

- (NSArray *)getUsersByStatusText:(NSString *)text screenName:(NSString *)screenName{
    //创建查询请求
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Status"];
    //设置查询条件
    request.predicate = [NSPredicate predicateWithFormat:@"text LIKE '*Watch*'",text];
    //获取查询结果
    NSArray *statuses = [self.context executeFetchRequest:request error:nil];
    //下面是用谓词对上面的结果进行过滤
    NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"user.screenName=%@",screenName];
    //对查询结果再进行过滤
    NSArray *users = [statuses filteredArrayUsingPredicate:userPredicate];
    return users;
}

7. 修改数据

只需要拿到对应的关联对象,直接修改,然后保存

- (void)modifyClasses:(Classes *)classes
{    
    classes.name = @"吊炸天毕业(1)班";
    NSError *error;
    if (![self.context save:&error]) {
        NSLog(@"修改过程中发生错误,错误信息:%@",error.localizedDescription);    
    }
}

四、CoreData调试

事实上在Xcode中是支持CoreData调试的,具体操作:
  • Product->Scheme
  • Scheme->Edit Scheme
  • Edit Scheme->Run
  • Run->Arguments
    依次添加两个参数(注意参数顺序不能错):
CoreData调试设置

然后在运行程序过程中,如果操作了数据库,就会将SQL语句打印在输出面板。

注意:如果模型发生了变化,此时可以重新生成实体类文件,但是所生成的数据库并不会自动更新,这时需要考虑重新生成数据库并迁移原有的数据。

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

推荐阅读更多精彩内容