前言
在开发记账软件的过程中,最重要的一点便是数据的本地化持久储存了,考虑到数据可能比较大,NSUserDefaults并不适用,于是决定用CoreData来储存用户记下的账本数据,但是当我看到起码几十页的文档,我的内心是崩溃的。。。再加上懒癌发作,我的项目一度搁浅。不过几天后下定决心,花了一小时把CoreData的文档整个的看了一遍,我流下了感动的泪水,苹果的文档真是良心出品啊!各个概念讲的非常清楚,所以这里我想要做一个简单的教程,希望能帮到与我有相同困扰的同学~
注:这个教程仅限于快速入门,讲究的是实用性,一些专业术语我为了好理解就简化了,如果想要认真搞清楚每个概念,还是推荐读一读官方文档
一、CoreData模型的创建
首先呢我们需要创建CoreData的基本使用环境,这步非常简单,创建项目时勾一下就好了。当然你可能会问要是我项目不是新建的已经做到一半想要加入CoreData怎么办? 反正我当初还是这样新建了一个项目,然后把原来项目里的东西都拖到新项目里了。。。 被自己的机智所打动~
然后就会发现比平时多出一个文件,就是那个后缀是xcdatamodeld的文件,我们就是在这里创建我们的储存对象的。然后点击下面的Add Entity
注意左边圆圈里的ENTITIES,这个就是你要储存的对象,本例中取作Account,就是用户储存的一笔账,这个命名很重要!后面一直要用到。然后就是每一个对象会有自己的属性,点击箭头所指的加号就可以创建,比如记一笔账,要记录记账的日期(date)、金额(money)、类别(type)、开支类型(isIncome)、还有详细情况(detail),你还可以定义每一个属性的Type,因为考虑到到时候要显示在Label上,我这里都设为String类型的,你可以根据自己的情况设定,完成之后是这个样子。
接下来就是自定义储存对象的类了,不用担心,这一步xcode可以帮我们完成!如图,点击上方Editor的Create NSManagedObject Subclass...
然后一路点确定,就会看到我们多出来四个文件,先不用管它们,让我们直接看xcode在AppDelegate中为我们生成的代码,大概长这样
先平复一下心情,你可能已经被一大串陌生的名词给弄晕了,什么NSManagedObjectModel、NSPersistentStoreCoordinator、还有NSManagedObjectContext。当初我看到时脸上也是一个大写的懵逼。。 但是后来我发现了,如果想我这样只想简单的储存一些数据,这些根本都不用管!你只要关注一下managedObjectContext就好了,这个有点类似数据库中的table,你的那些数据对象都是存在里面,当你退出应用时数据也是由它自动帮你保存到持久化数据层,这个是你几乎唯一会用上的东西(当然我还是建议再基本掌握之后还是要回过头来研究一下它们),好了,看完之后我们就进入下一阶段(纳尼?!只要看一下就好? 是的。。。)
二、CoreData数据的储存
上一阶段我们该做的准备工作已经做完了,接下来就是真正的进行我们的实战了。本例以一个账本存取的过程演示如何进行数据的存取。假如我们现在要存一笔账,那你只要进行一下几步:
1.先获取AppDelegate单例,然后取得它的属性(在appDelegate中定义的,我们可以暂时不管它的具体实现,只要知道这是它的一个属性就好了)
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
2.存入数据,这里用到了一个方法,第一个参数是要我们之前设置的Entity的名字,就是我说的很重要的那个,这里要告诉它你要存的是哪一个对象,后一个参数就是我们刚刚取得的managedObjectContext。 其实总结起来就是你把一个数据(Account)存到一个表里(managedObjectContext),然后这个方法会返回你存的那个数据,它的类型是Account,是的,就是刚刚xcode自动帮我们生成的那四个文件,那个类就是Account(你给数据对象取得名字)
Account *account = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:managedObjectContext];
3.最后一步就是设置你要存入数据对象的各种属性了,就是我们最先创建的那些,日期、金额那些。这里要注意CoreData的数据对象默认是只能用键值对赋值的,也就是setValue: forKey: 方法,十分繁琐,但是这里我们自定义了一个子类的好处就显现出来了,我们可以直接用点语法的设置方法,代码如下
account.incomeType = 你要存入数据的收支类型;
account.date = 你要存入数据的日期;
...
然后就可以了,只要简单的三步就完成了数据的储存~
三、CoreData数据的读取
现在数据储存好了,我们希望下次用户再次进入的时候就把他先前存的数据展示出来,就涉及到数据的读取了,事实上这一步甚至更简单,代码如下
1创建NSFetchRequest,这个就是用来取出数据的
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Account"];
2.设置一个NSPredicate用来筛选数据,比如我这里只要取出uniqueDate日期的Account
[request setPredicate:[NSPredicate predicateWithFormat:@"date == %@", uniqueDate]];
3.取得数据,存在数组resultArray里,
NSError *error = nil;
resultArray = [managedObjectContext executeFetchRequest:request error:&error];
然后,就可以按你的需要处理这些数据啦~
CoreData在应用中的实际运用可以参考https://github.com/XinStar1/AZXTallyBook 感兴趣的可以去看下,觉得好可以star一下~
注:官方文档中有专门把数据显示在UITableView的类,因为此处的数据类型比较简单,故未用该方法,如果感兴趣的可以去研究一下
注:大家如果遇到退出应用而数据未被保存的情况,可以打开AppDelegate文件,找到这个方法
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
这个方法就是在应用要退出时保存我们的数据,然而这个非常不稳定,有一定概率不保存。。。 所以可以将[self saveContext];这一句移到
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[self saveContext];
}
就像官方的注释所讲的,如果你的程序支持后台运行,那这调用的就不是applicationWillTerminate而是这个方法了。
四、结语
其实看下来,如果只是储存一些简单的数据,CoreData的使用还是非常简单的,很大一部分的应用都会涉及到数据的储存,所以研究一下CoreData还是非常有必要的。当然此处为了易操作很多概念我都没有细讲,不过想必大家在跟随教程成功操作后就不会觉得CoreData多么难了,这时候再去仔细看一遍文档,相信就能更好的掌握了。