zoukankan      html  css  js  c++  java
  • IOS数据存储之CoreData使用优缺点

    前言:

       学习了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

        第二步:创建xxxx.xcdatamodeld

         第三步:模型对象的实体

    接下来就是具体实现:具体实现之前先来认识如下几个对象

    (1)NSManagedObjectModel(被管理的对象模型)

               相当于实体,不过它包含 了实体间的关系

      (2)NSManagedObjectContext(被管理的对象上下文)

             操作实际内容

            作用:插入数据  查询  更新  删除

     (3)NSPersistentStoreCoordinator(持久化存储助理)

              相当于数据库的连接器

       (4)NSFetchRequest(获取数据的请求)    

            相当于查询语句

       (5)NSPredicate(相当于查询条件)

       (6)NSEntityDescription(实体结构)

    为了方便实现,本文整理一个数据管理类来测试CoreData:CoreDataManager

    CoreDataManager.h

    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
    
    @interface CoreDataManager : NSObject<NSCopying>
    
    @property(strong,nonatomic,readonly)NSManagedObjectModel* managedObjectModel;//管理数据模型
    
    @property(strong,nonatomic,readonly)NSManagedObjectContext* managedObjectContext;//管理数据内容
    
    @property(strong,nonatomic,readonly)NSPersistentStoreCoordinator* persistentStoreCoordinator;//持久化数据助理
    
    //创建数据库管理者单例
    +(instancetype)shareManager;
    
    //插入数据
    -(void)insertData:(NSString*)tempName;
    
    //删除数据
    -(void)deleteData;
    
    //删除数据
    -(void)deleteData:(NSString*)tempName;
    
    //查询数据
    -(void)queryData;
    
    //根据条件查询
    -(void)queryData:(NSString*)tempName;
    
    //更新数据
    -(void)updateData:(NSString*)tempName;
    
    @end
    View Code

    CoreDataManager.m

    #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 的数据模型升级兼容性比较差,如果模型不对,会导致程序连起都起不来。虽然提供了模型升级代码,但是在客户端的管理模型版本管理也会相对复杂。

  • 相关阅读:
    day7 面向对象 静态方法 类方法 属性方法 类的特殊成员方法 元类 反射 异常处理
    day6 面向对象 封装 继承 多态 类与实例在内存中的关系 经典类和新式类
    day5 time datetime random os sys shutil json pickle shelve xml configparser hashlib subprocess logging re正则 python计算器
    kafka常用操作命令
    linux基础
    django学习1——初识web应用程序
    mysql数据库(三)——pymysql模块
    mysql数据库(二)——表的查询
    mysql数据库(一)
    Python常用模块——re模块
  • 原文地址:https://www.cnblogs.com/whoislcj/p/5488024.html
Copyright © 2011-2022 走看看