数据存储之CoreData(基础)

ios开发常用的五种数据存储方式:

  • plist
  • NSUserDefaults
  • NSKeyedArchiver
  • FMDB
  • CoreData

这篇文章我们主要回顾Core Data的使用

Core Data

因为Core data涉及到的东西较多,在这里先写一些入门的操作(多表关联以后会更新)
core data涉及到的一些类:

 (1)NSManagedObjectContext(被管理的数据上下文)
    操作实际内容(操作持久层)
    作用:插入数据,查询数据,删除数据
 (2)NSManagedObjectModel(被管理的数据模型)
    数据库所有表格或数据结构,包含各实体的定义信息
    作用:添加实体的属性,建立属性之间的关系
    操作方法:视图编辑器,或代码
 (3)NSPersistentStoreCoordinator(持久化存储助理)
    相当于数据库的连接器
    作用:设置数据存储的名字,位置,存储方式,和存储时机
 (4)NSManagedObject(被管理的数据记录)
    相当于数据库中的表格记录
 (5)NSFetchRequest(获取数据的请求)
    相当于查询语句
 (6)NSEntityDescription(实体结构)
    相当于表格结构,NSEntityDescription对象包含了Entity所拥有的属性,关系等信息,我们可以通过NSEntityDescription生成相应的NSManagedObject的实体

coredata的使用

1.创建coreDataDemo 如图选中User Core Data


90FF46FE-6465-49C2-9FD7-3CDAA95D6855.png

“Use Core Data”这个勾给我们做了些额外的工作,一是将“CoreData.framework”增加到我们工程的Frameworks列表中来了,二是在AppDelegate中增加了一些关于CoreData的代码.
如果你的工程没勾选“Use Core Data”这个选项,你也可以模仿一个新创建的“Use Core Data”的工程把必要的代码添加上去,完全没问题.
选中


屏幕快照 2016-11-29 下午8.57.28.png

2.添加实体
53464188-A7E9-46C4-B46D-2FBF96C0C8B9.png

3.然后新建一个file,记得是NSManagedObject cubclass

5556A2E1-D835-4007-AC99-72A6CD50DF3F.png
0E3675FA-EC3C-47A5-8391-9B9C5E01D3D9.png
BA7400A0-AEFB-4114-9726-FC643F3121B1.png

生成四个文件(ios7之前是两个)

屏幕快照 2016-11-30 下午12.40.07.png

4.代码示例

下面我们建立一个单例来演示coredate的 增、删、改、查功能

(1) 增

//增
-(BOOL)saveCarInfoByCarModel:(CarModel *)carmodel
{
    BOOL retVal = NO;
    //NSManagedObjectContext(被管理的数据上下文),操作实际内容(操作持久层)作用:插入数据,查询数据,删除数据
    NSManagedObjectContext *context = [APPDELEGATE managedObjectContext];
    //下面代码相当于 alloc init 初始化
    Car *car = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:context];
    car.userID = carmodel.userID;
    car.carID = carmodel.carID;
    car.carName = carmodel.carName;
    car.carNumber = carmodel.carNumber;
    car.carIsDefault = carmodel.carIdDefault;
    NSError *error;
    if ([context save:&error]) {
        NSLog(@"保存成功");
        retVal = YES;
    }
    return retVal;
}


在VC中执行

-(void)insertAction
{
   CarModel *carmodel = [[CarModel alloc]init];
   carmodel.userID = @"2011";
   carmodel.carID = @"1dwdwq";
   carmodel.carName = @"兰博基尼";
   carmodel.carNumber = @"京A93459";
   carmodel.carIdDefault = @"0";
   if ([[SingleTon sharedSingleTon] saveCarInfoByCarModel:carmodel]) {
       NSLog(@"插入数据成功");
     }
}


在此之前我们需要在appdelegate中打印数据库的地址便于查看数据信息

F65A0799-062D-4FBF-80A1-3835F27AA2C1.png

运行结果如下:

2016-11-30 12:51:29.163 coreDataDemo[31612:1990693] file:///Users/x8f/Library/Developer/CoreSimulator/Devices/7A1AE587-2880-40CE-A11B-17F7DFE94ACD/data/Containers/Data/Application/D66488E1-0E5E-44F8-B75A-5C44DD5954CF/Documents/coreDataDemo.sqlite
2016-11-30 12:51:29.174 coreDataDemo[31612:1990693] 保存成功
2016-11-30 12:51:29.174 coreDataDemo[31612:1990693] 插入数据成功


前往-->前往文件夹-->输入数据库地址后看到:

屏幕快照 2016-11-30 下午12.53.26.png

使用SQLiteManager打开数据库文件
数据库下载地址:https://github.com/skyxian/SQLiteManager
屏幕快照 2016-11-30 下午12.53.50.png

屏幕快照 2016-11-30 下午12.54.12.png

数据添加成功 !
然后我们再多添加几个数据便于改、删、查的操作演示
我添加了六条数据如下:

1.02.33.png

(2) 删

//删:根据carID来删除carID对应的那个车辆
-(BOOL)deleteCarInfoByCarID:(NSString *)carID
{
   BOOL retVal = NO;
   NSManagedObjectContext *context = [APPDELEGATE managedObjectContext];
   //建立请求
   NSFetchRequest *request = [[NSFetchRequest alloc]init];
   //读取所有Car
   NSEntityDescription *entity = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:context];
   request.entity = entity;
   //设置检索条件(不设则默认检索所有Car)
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"carID=%@",carID];
   request.predicate = predicate;
   NSError *error;
   NSArray *arr = [context executeFetchRequest:request error:&error];
   if (arr.count) {
       for (Car *car in arr) {
           //删除对象
           [context deleteObject:car];
       }
       //保存删除的结果
       if ([context save:nil]) {
           retVal = YES;
       }
   }else{
       NSLog(@"没有检索到对象");
   }
   return retVal;
}


VC中我们执行 删除carID = @"e28r22"的那个car对象的操作

-(void)deleteAction
{
   CarModel *carmodel = [[CarModel alloc]init];
   carmodel.carID = @"e28r22";
   if ([[SingleTon sharedSingleTon] deleteCarInfoByCarID:carmodel.carID]) {
      NSLog(@"删除数据成功");
   }
}


打印结果如下:

2016-11-30 13:15:33.410 coreDataDemo[31862:2004730] file:///Users/x8f/Library/Developer/CoreSimulator/Devices/7A1AE587-2880-40CE-A11B-17F7DFE94ACD/data/Containers/Data/Application/6A977C79-3A51-449D-8D5E-EF5F8009D2EA/Documents/coreDataDemo.sqlite
2016-11-30 13:15:33.417 coreDataDemo[31862:2004730] 删除数据成功


我们打开数据库查看

1.18.15.png

carID为@"e28r22"的那个car对象被我们成功删除!

(3) 改

由上图我们看到数据库还有5条数据,现在我们修改userid为2012 carid为r3nkr3 的数据信息(coredata中使用&&连接符)

//改:根据userID以及carID来修改车辆信息
-(BOOL)updateCarInfoByCarModel:(CarModel *)carmodel
{
    BOOL retVal = NO;
    NSManagedObjectContext *context = [APPDELEGATE managedObjectContext];
    //建立请求
    NSFetchRequest *request = [[NSFetchRequest alloc]init];
    //读取所有Car
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:context];
    request.entity = entity;
    //设置检索条件(不设则默认检索所有Car)
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userID = %@ && carID = %@",carmodel.userID,carmodel.carID];
    request.predicate = predicate;
    NSError *error;
    NSArray *arr = [context executeFetchRequest:request error:&error];
    if (arr.count) {
        for (Car *car in arr) {
            car.userID = carmodel.userID;
            car.carID = carmodel.carID;
            car.carIsDefault = carmodel.carIdDefault;
            car.carName = carmodel.carName;
            car.carNumber = carmodel.carNumber;
            if ([context save:nil]) {
                retVal = YES;
            }
        }
    }else{
        NSLog(@"没有检索到对象");
      }
    return retVal;
}


在VC中执行

-(void)updateAction
{
   CarModel *carmodel = [[CarModel alloc]init];
   carmodel.userID = @"2012";
   carmodel.carID = @"r3nkr3";
   carmodel.carName = @"路虎";
   carmodel.carNumber = @"京A80808";
   carmodel.carIdDefault = @"1";
   if ([[SingleTon sharedSingleTon] updateCarInfoByCarModel:carmodel]) {
       NSLog(@"更新数据成功");
   }
}


去数据库查看

BCB302D6-83F6-4410-9DAC-5DA5EA91D8A1.png

userid为2012 carid为r3nkr3 的数据被成功修改

(4) 查

我们来查找所有userid为2010的车辆信息

// 查:根据userID查寻该userID对应的所有车辆
-(NSArray *)queryCarInfoByUserID:(NSString *)userID
{
   NSManagedObjectContext *context = [APPDELEGATE managedObjectContext];
   //建立请求
   NSFetchRequest *request = [[NSFetchRequest alloc]init];
   //读取所有Car
   NSEntityDescription *entity = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:context];
   request.entity = entity;
   //设置检索条件(不设则默认检索所有Car)
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userID = %@",userID];
   request.predicate = predicate;
   NSError *error;
   NSMutableArray *listArr = [NSMutableArray new];
   NSArray *arr = [context executeFetchRequest:request error:&error];
   for (Car *car in arr) {
       CarModel *model = [[CarModel alloc]init];
       model.userID = car.userID;
       model.carID = car.carID;
       model.carIdDefault = car.carIsDefault;
       model.carName = car.carName;
       model.carNumber = car.carNumber;
       [listArr addObject:model];
   }
   return listArr;
}   


VC中执行

-(void)queryAction
{
   CarModel *carmodel = [[CarModel alloc]init];
   carmodel.userID = @"2010";
   NSArray *arr = [[SingleTon sharedSingleTon]queryCarInfoByUserID:carmodel.userID];
   if (arr) {
     for (CarModel *model in arr) {
         NSLog(@"%@---%@---%@---%@---%@",model.userID,model.carID,model.carName,model.carNumber,model.carIdDefault);
     }
   }
}


打印结果如下

2016-11-30 13:35:24.914 coreDataDemo[31986:2016010] file:///Users/x8f/Library/Developer/CoreSimulator/Devices/7A1AE587-2880-40CE-A11B-17F7DFE94ACD/data/Containers/Data/Application/99FCBB9B-41BD-460F-BF23-7231126FDFC4/Documents/coreDataDemo.sqlite
2016-11-30 13:35:24.919 coreDataDemo[31986:2016010] 2010---29eh4f---法拉利---京A429e8---1
2016-11-30 13:35:24.919 coreDataDemo[31986:2016010] 2010---bi3k1---大众---京A82eb2---0
2016-11-30 13:35:24.919 coreDataDemo[31986:2016010] 2010---9d20d2---蒙迪欧---京A11111---0


查询成功 !

数据迁移

假设存在这样一个场景,car这个实体现有的属性字段已经无法满足我们的需求,需要给它添加几个字段并修改原有的部分字段,这个时候我们就需要使用数据迁移了,否则程序会crash!
ok !我们在本demo中继续演示 版本迁移
(1) 选中你的coreDataDemo.xcdatamodeld文件,选择Xcode菜单editor->Add Model Version
比如取名:coreDataDemo 2.xcdatamodel

屏幕快照 2016-11-30 下午2.25.21.png
1628981F-4EEC-4084-BBCE-56FEC8D70CE9.png

这个时候你会发现CoreData.xcdatamodeld中多了一个版本文件,如图:

屏幕快照 2016-11-30 下午2.39.05.png

(2) 选择刚才创建的版本,在inspector中的Versioned Core Data Model选择Current模版为coreDataDemo 2.xcdatamodel


451AC5F8-650F-4D14-9971-8B88CE127F9D.png

(3) 修改新数据模型coreDataDemo 2,在新的文件上添加属性字段和修改实体 ( 切记!!!是在新的coreDataDemo 2上添加及修改属性)

9326245E-F836-4E78-AAEB-5C1376ABBFBC.png

(4) 修改原来的实体文件(或者删除原来的实体文件,重新生成新的实体下的类)

C38126DA-403D-4EC3-A6C1-F3F69D00DE20.png
1CF7413C-187E-431B-BC84-AD22EFC67730.png

(5)在AppDelegate.m的persistentStoreCoordinator中添加代码:

758E84FB-E3E8-4DBC-A74C-EFB22D63EFC9.png

运行--成功 !
现在我们再次向数据库中添加一条数据看看有什么效果

-(void)insertAction
{
    /*
     *
     *  这里最好多添加几条数据便于后面 删、改、查 的操作演示
     *
     */
    CarModel *carmodel = [[CarModel alloc]init];
    carmodel.userID = @"2013";
    carmodel.carID = @"8f3hf3";
    carmodel.carName = @"法拉利";
    carmodel.carNumber = @"京A86868";
    carmodel.carIdDefault = @"0";
    if ([[SingleTon sharedSingleTon] saveCarInfoByCarModel:carmodel]) {
        NSLog(@"插入数据成功");
    }
}


打印结果:

2016-11-30 15:02:35.063 coreDataDemo[32513:2055137] file:///Users/x8f/Library/Developer/CoreSimulator/Devices/7A1AE587-2880-40CE-A11B-17F7DFE94ACD/data/Containers/Data/Application/EF713FA9-E1D0-4E42-BC6A-CBBF438AB4A9/Documents/coreDataDemo.sqlite
2016-11-30 15:02:35.136 coreDataDemo[32513:2055137] 保存成功
2016-11-30 15:02:35.136 coreDataDemo[32513:2055137] 插入数据成功


进入数据库查看

05AA1904-6652-4518-8DB1-32DE310443CD.png

数据添加成功,且数据库中多了一个carDistance的字段,说明数据迁移成功!

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

推荐阅读更多精彩内容