Core Data的那点事儿~

一、介绍下Core Data

  CoreData在早些年iOS开发中使用不多,因为其本身性能略低,以及不使用SQL语句而失去的灵活性,再加上FMDB之类封装SQLite的三方框架很好用,所以一直不受待见。最近越来越多的开发中开始使用CoreData,原因也许是因为如今的设备性能的提升,大家又慢慢的看到了CoreData的优点,比如不用SQL语句(笔者很喜欢这点,哈哈),配置使用的方式也比较简单(刚开始使用时可能感觉有点复杂,用于连接“对象”和“关系”的类好多。。但是模式本身是很简单的,也很容易实现,熟练而已)。

  下面开始好好聊聊CoreData吧,看完至少使用它不再是问题~

  Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句,这个有点类似于著名的Hibernate持久化框架,不过功能肯定是没有Hibernate强大的。

  CoreData本质是一个ORM框架 ORM Objective-Relational Mapping 这个映射就是我们的模型文件,一般ORM框架都用XML格式来映射实体Entity+属性数据库表。

  托管对象(entity) —既不是单纯的内存对象,也不是数据库中的具体的数据,它介于这两个状态之间的,我们叫他游离态的数据(很蛋疼的说法)。

  CoreData不能执行SQL语句,取而代之,操作的是对象, FMDB SQLite可以直接SQL语句,对于很多面向对象的开发者来说,操作对象更为习惯。

  给出一张图,看看“关系”和“对象”

  •  左边是关系模型,即数据库,数据库里面有张person表,person表里面有id、name、age三个字段,而且有2条记录; 右边是对象模型,可以看到,有2个OC对象; 利用Core Data框架,我们就可以轻松地将数据库里面的2条记录转换成2个OC对象,也可以轻松地将2个OC对象保存到数据库中,变成2条表记录,而且不用写一条SQL语句。

   

 

二、coredata中的核心对象

    

注:黑色表示类名,红色表示类里面的一个属性

1、常规开发步骤(不理解没关系,后面有代码。。):

  (1)初始化NSManagedObjectModel对象,加载模型文件,读取app中的所有实体信息

  (2)初始化NSPersistentStoreCoordinator对象,添加持久化库(这里采取SQLite数据库)

  (3)初始化NSManagedObjectContext对象,拿到这个上下文对象操作实体,进行CRUD(创建(Create)、更新(Update)、读取(Read)和删除(Delete))操作

2、核心对象

(1)CoreData 持久化协调器 - NSPersistentStoreCoordinator

NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]

(2)CoreData 对象映射模型 - NSManagedObjectModel

_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

(3)CoreData 托管对象上下文 - NSManagedObjectContext

  1. 指定队列 _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
  2. 指定协调器 [_managedObjectContext setPersistentStoreCoordinator:coordinator];

(4)CoreDate 实体描述器 - NSEntityDescription

(5)CoreData 托管对象 - NSManageObject

 

三、CoreData的4个存储方式:

  1. SQLite         NSSQLiteStoreType
  2. XML            NSXMLStoreType
  3. Binary         NSBinaryStoreType
  4. 内存存储       NSInMemoryStoreType     这是个及其鸡肋的存储方式。。。。

 

四、看代码吧~~~配置示例

1、创建一个CoreData管理工具类,方便使用“管理上下文”

@implementation ZQManagerCoreData

//单例实现
static ZQManagerCoreData *share;
+(instancetype)shareManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
       share =  [[ZQManagerCoreData alloc]init];
    });
    return share;
}


//通过getter方法获取上下文:

/*
    1、生成上下文需要设置持久化存储协调器!

    2、生成协调器又需要一个模型  

    3、新创建一个CoreData选项下的Data Model模型文件 

    4、把这个模型文件从bundle中加载到

*/
-(NSManagedObjectContext *)managedContext
{
    if (_managedContext == nil) {

        //模型文件的boundle 路径
        NSURL *url = [[NSBundle mainBundle] URLForResource:@"Person" withExtension:@"momd"];
        
        //需要一个模型文件
        NSManagedObjectModel *model = [[NSManagedObjectModel alloc]initWithContentsOfURL:url];
        
        //创建持久化存储协调器
        NSPersistentStoreCoordinator *per = [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:model];
        
        //创建对象
        _managedContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSMainQueueConcurrencyType];
    //数据库文件路径

#warning 文件路径放在桌面是随意选的,应该放在沙盒最好

        NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/apple/Desktop/Person/person.db"];
        //添加数据库文件路径
        [per addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:fileUrl options:nil error:nil];
        //设置参数
        [_managedContext setPersistentStoreCoordinator:per];
        
    }
    return _managedContext;
    
}
    

2、存储数据到数据库

//存储数据
- (void)updata
{
    //通过“实体描述”的类方法 insert 插入数据

/*
    1、“实体描述”的类方法,需要实体,要到刚才创建的model文件中去添加实体(点击),同时注意实体的名字首字母必须大写!添加完Entity“实体”以后,设置这个实体的属性,就是对应数据库中的字段

    2、“实体描述”的类方法返回的是OC的对象(NSManagedObject),此对象比较特殊,是“游离”对象

    3、手动创建一个NSManagedObject的类文件,注意,不是普通的iOS源文件,是通过CoreData选项中的NSManagedObject ect subclass 创建的特殊类。这个类要关联刚才创建的model和model里面的实体,关联在创建的过程中点击就实现了,创建完毕后会多出四个文件(Xcode7新特性,原来是两个文件)

    4、导入生成文件的头文件,声明变量接收一下“实体描述”的类方法返回的值

    5、对这个对象进行属性操作,就是对数据库中的字段进行操作了!

    6、最后,使用“管理上下文”保存,就真正的写入数据库了。

*/
  Person *person =  [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:[ZQManagerCoreData shareManager].managedContext];
    
    
    //修改person对象的属性
    person.name = @"lisi";
    person.age = @(18);
    
    //告诉数据库存储数据
    [[ZQManagerCoreData shareManager].managedContext save:nil];
}   

3、从数据库中读取

//取数据 fetch
- (void)fetch
{
        
/*
    1、通过“管理上下文”  执行 “请求” 实现取数据

    2、创建一个“请求”,需要配置三个属性

    (1)需要一个实体描述,和保存时一样
    (2)需要一个谓词,设置检索的条件
    (3)需要一个排序,将什么属性,按照什么方式排序

    3、查询结果是数组,拿数组接一下,数组里面是满足条件的对象(NSManageObject,这里是子类Person)

*/

    //需要一个查询请求
    NSFetchRequest *fetchrequest = [[NSFetchRequest alloc]init];
    
    //需要一个实体描述
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:[ZQManagerCoreData shareManager].managedContext];
    fetchrequest.entity = entity;
    
    //需要一个谓词 相当于SQL语句中的where 条件判断
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"age = %@",@"18"];
    fetchrequest.predicate = pre;
    
    //需要一个排序
    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
    fetchrequest.sortDescriptors = @[sort];
    
    //执行查询请求
   NSArray *tempArray = [[ZQManagerCoreData shareManager].managedContext executeFetchRequest:fetchrequest error:nil];
    
    //打印结果
    for (Person *person in tempArray) {
        NSLog(@"person = %@",person.name);
    }
}        

另外,Xcode的友好提示:输入关键字 fetch ,系统会提示使用CoreData代码块,可以自动填充上面的取数据代码~~

原文地址:https://www.cnblogs.com/cleven/p/5475583.html