IOS数据存储之CoreData使用优缺点
2016-05-13 01:21
537 查看
前言:
学习了Sqlite数据之后认真思考了一下,对于已经习惯使用orm数据库的开发者或者对sql语句小白的开发者来说该如何做好数据库开发呢?这个上网搜了一下?看来总李多虑了!apple 提供了一种数据方式,它就是今天的主角:CoreData!我们一起来探究它是否能够满足我们项目开发的需要呢?
CoreData介绍:
Core Date是ios3.0后引入的数据持久化解决方案,它是是苹果官方推荐使用的,不需要借助第三方框架。Core Date实际上是对SQLite的封装,提供了更高级的持久化方式。在对数据库操作时,不需要使用sql语句,也就意味着即使不懂sql语句,也可以操作数据库中的数据。
CoreData优点:
Core Data实际上是将数据库的创建、表的创建、对象和表的转换等操作封装起来,极大的简化了我们的操作。Core Date与SQLite相比较,SQLite比较原始,操作比较复杂,使用的是C的函数对数据库进行操作,但是SQLite可控性更强,并且能够跨平台。
CoreData缺点:
存储性能一般,默认建立的表没有主键,效率低,复杂的查询更是不敢想像。CoreData 对批量数据的处理执行的不太好,查资料好像说IOS8推出了批量处理的一些方式。对于多线程的支持也不太好,我是xcode 7上开发的每一个entity都要生成4个类,打个比方一个项目中要建10个表那就要维护40个类,你说累不累?
怎么使用CoreData?
第一步:在项目中引入CoreData.framework
View Code
具体使用方式
测试一下效率:测试数据10000条
运行结果:
第一种:8.408
第二种:0.162
但是有个超级大的问题,第二种方式虽然效率高,但是插入数据乱序。第一种正常但是效率超低,同样近似的数据量sqlite效率比这个高不知多少倍。如果用这个来做数据库开发我觉得是无爱了。批量操作支持的不太好。对于它的数据库升级也不想过多了解。所以就随便查了下,得出如下结论:CoreData 的数据模型升级兼容性比较差,如果模型不对,会导致程序连起都起不来。[b]虽然提供了模型升级代码,但是在客户端的管理模型版本管理也会相对复杂。
[/b]
学习了Sqlite数据之后认真思考了一下,对于已经习惯使用orm数据库的开发者或者对sql语句小白的开发者来说该如何做好数据库开发呢?这个上网搜了一下?看来总李多虑了!apple 提供了一种数据方式,它就是今天的主角:CoreData!我们一起来探究它是否能够满足我们项目开发的需要呢?
CoreData介绍:
Core Date是ios3.0后引入的数据持久化解决方案,它是是苹果官方推荐使用的,不需要借助第三方框架。Core Date实际上是对SQLite的封装,提供了更高级的持久化方式。在对数据库操作时,不需要使用sql语句,也就意味着即使不懂sql语句,也可以操作数据库中的数据。
CoreData优点:
Core Data实际上是将数据库的创建、表的创建、对象和表的转换等操作封装起来,极大的简化了我们的操作。Core Date与SQLite相比较,SQLite比较原始,操作比较复杂,使用的是C的函数对数据库进行操作,但是SQLite可控性更强,并且能够跨平台。
CoreData缺点:
存储性能一般,默认建立的表没有主键,效率低,复杂的查询更是不敢想像。CoreData 对批量数据的处理执行的不太好,查资料好像说IOS8推出了批量处理的一些方式。对于多线程的支持也不太好,我是xcode 7上开发的每一个entity都要生成4个类,打个比方一个项目中要建10个表那就要维护40个类,你说累不累?
怎么使用CoreData?
第一步:在项目中引入CoreData.framework
#import "CoreDataManager.h" #import "Car.h" static CoreDataManager *shareManager=nil; @implementation CoreDataManager @synthesize managedObjectContext =_managedObjectContext; @synthesize managedObjectModel = _managedObjectModel; @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; //实例化对象 -(instancetype)init { self=[super init]; if (self) { } return self; } //创建数据库管理者单例 +(instancetype)shareManager { //这里用到了双重锁定检查 if(shareManager==nil){ @synchronized(self){ if(shareManager==nil){ shareManager =[[[self class]alloc]init]; } } } return shareManager; } -(id)copyWithZone:(NSZone *)zone { return shareManager; } +(id)allocWithZone:(struct _NSZone *)zone { if(shareManager==nil){ shareManager =[super allocWithZone:zone]; } return shareManager; } //托管对象 -(NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel!=nil) { return _managedObjectModel; } NSURL* modelURL=[[NSBundle mainBundle] URLForResource:@"myCoreData" withExtension:@"momd"]; _managedObjectModel=[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return _managedObjectModel; } //托管对象上下文 -(NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext!=nil) { return _managedObjectContext; } NSPersistentStoreCoordinator* coordinator=[self persistentStoreCoordinator]; if (coordinator!=nil) { _managedObjectContext=[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];//NSMainQueueConcurrencyType NSPrivateQueueConcurrencyType [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } //持久化存储协调器 -(NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator!=nil) { return _persistentStoreCoordinator; } NSString* docs=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]; NSURL* storeURL=[NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"myCoreData.sqlite"]]; NSLog(@"path is %@",storeURL); NSError* error=nil; _persistentStoreCoordinator=[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@"Error: %@,%@",error,[error userInfo]); } return _persistentStoreCoordinator; } //插入数据 -(void)insertData:(NSString*)tempName { //读取类 Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; car.name=tempName; //保存 NSError *error; [self.managedObjectContext save:&error]; } //删除数据 -(void)deleteData { //创建读取类 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //启动查询 NSError *error; NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error]; if(deleteArr.count){ for (Car *car in deleteArr) { [self.managedObjectContext deleteObject:car]; } NSError *error; [self.managedObjectContext save:&error]; }else{ NSLog(@"未查询到可以删除的数据"); } } //删除数据 -(void)deleteData:(NSString*)tempName; { //创建读取类 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //创建检索条件 NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName]; [request setPredicate:predicate]; //启动查询 NSError *error; NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error]; if(deleteArr.count){ for (Car *car in deleteArr) { [self.managedObjectContext deleteObject:car]; } NSError *error; [self.managedObjectContext save:&error]; }else{ NSLog(@"未查询到可以删除的数据"); } } //查询数据 -(void)queryData { //创建读取类 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //启动查询 NSError *error; NSArray *carArr=[self.managedObjectContext executeFetchRequest:request error:&error]; for(Car *car in carArr){ NSLog(@"car---->%@",car.name); } } -(void)queryData:(NSString*)tempName { //创建读取类 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //创建检索条件 NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName]; [request setPredicate:predicate]; //启动查询 NSError *error; NSArray *carArr=[self.managedObjectContext executeFetchRequest:request error:&error]; for(Car *car in carArr){ NSLog(@"car---->%@",car.name); } } //更新数据 -(void)updateData:(NSString*)tempName { //创建读取类 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //创建检索条件 NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName]; [request setPredicate:predicate]; //启动查询 NSError *error; NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error]; if(deleteArr.count){ for (Car *car in deleteArr) { car.name=@"test"; } NSError *error; [self.managedObjectContext save:&error]; }else{ NSLog(@"未查询到可以删除的数据"); } } @end
View Code
具体使用方式
//清空数据 [[CoreDataManager shareManager]deleteData]; //插入10条数据 for(int i=0;i<10;i++){ NSString *string = [[NSString alloc] initWithFormat:@"%d",i]; [[CoreDataManager shareManager]insertData:string]; } //然后查询一下 [[CoreDataManager shareManager]queryData]; //然后删除一条数据 [[CoreDataManager shareManager]deleteData:@"5"]; //然后查询一下 [[CoreDataManager shareManager]queryData]; // 更新数据 [[CoreDataManager shareManager]updateData:@"3"]; //然后查询一下 [[CoreDataManager shareManager]queryData]; //清空数据 [[CoreDataManager shareManager]deleteData]; //然后查询一下 [[CoreDataManager shareManager]queryData];
测试一下效率:测试数据10000条
NSMutableArray *testArray =[[NSMutableArray alloc]init]; int testMaxCount =10000; for(int i=0;i<testMaxCount;i++){ NSString *string = [[NSString alloc] initWithFormat:@"%d",i]; [testArray addObject:string]; } //测试一下效率 第1种 CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); for(NSString *tempName in testArray){ [[CoreDataManager shareManager]insertData:tempName]; } CFAbsoluteTime end=CFAbsoluteTimeGetCurrent(); NSLog(@"coreData数据插入 time cost: %0.3f", end - start); //测试一下效率 第2种 start = CFAbsoluteTimeGetCurrent(); [[CoreDataManager shareManager]insertDatas:testArray]; end=CFAbsoluteTimeGetCurrent(); NSLog(@"coreData数据插入 time cost: %0.3f", end - start);
insertData函数:
//插入数据 -(void)insertData:(NSString*)tempName { //读取类 Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; car.name=tempName; //保存 NSError *error; [self.managedObjectContext save:&error]; }
insertDatas函数:
//插入数据 -(void)insertDatas:(NSArray*)tempNames { for(NSString *name in tempNames){ Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; car.name=name; } NSError *error; [self.managedObjectContext save:&error]; }
运行结果:
第一种:8.408
第二种:0.162
但是有个超级大的问题,第二种方式虽然效率高,但是插入数据乱序。第一种正常但是效率超低,同样近似的数据量sqlite效率比这个高不知多少倍。如果用这个来做数据库开发我觉得是无爱了。批量操作支持的不太好。对于它的数据库升级也不想过多了解。所以就随便查了下,得出如下结论:CoreData 的数据模型升级兼容性比较差,如果模型不对,会导致程序连起都起不来。[b]虽然提供了模型升级代码,但是在客户端的管理模型版本管理也会相对复杂。
[/b]
相关文章推荐
- 学习Coding-iOS开源项目日志(四)
- protobuf---真正-- 在IOS中的使用
- iOS 获取手机的型号,系统版本,设备名称等
- Access restriction: The type 'AudioStream' is not
- [10秒学会] - iOS NSAttributedString 首行缩进
- iOS基础开发-自定义控件
- iOS开发-----KVC与KVO的区别
- iOS基础开发-字典转模型(模型思想)
- iOS基础开发-懒加载
- iOS开发设置textFiled的placeholder颜色
- iOS基础开发-九宫格显示数据页面
- iOS内存管理(ARC,MRC)
- ios自定义控件——星星评分控件
- iOS学习——self和super关键字的解析
- iOS学习- 01 程序模版
- iOS中KVC和KVO的区别
- iOS开发中的错误整理,关于用绑定Tag取控件的注意事项,有时候不绑定也是个错!
- ios最简单的播放音频程序
- iOS开发中的错误整理,(百思项目,指示器位置)设置控件尺寸和点坐标,先设置尺寸,再设置点坐标
- 一篇文章看懂iOS代码块Block