您的位置:首页 > 移动开发 > IOS开发

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

#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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: