恩,用Core Data也有一段时间了。大大小小的坑也都坑过了。重来没有认真的记录一次。这次需要好好的理一理Core Data。就当一次绝好的机会记录下来。也为了自己加深认识。

为什么要用Core Data

CoreData的学习是需要一定成本的。以至于我认识的人很少在用,大家要不就是用一个FMDB。或者做的App是一个已有的Web的延伸,数据直接用Web端的Api取回来就好了。

我们要用Core Data的理由有以下几点:

  1. Core Data是对底层存储的一次封装。封装了以后就变成ORM的框架。这样就变成操作对象。Core Data自己去进行数据的保存。

  2. 使用Core Data而不是FMDB,让整个程序架构更加的面向对象。

  3. Core Data仅仅使用了Objective-C和Core Foundation,你不必去加入一些第三方的库。

  4. Core Data是Apple的原生技术。每年的WWDC都能看到新特性的加入和讲授。

  5. Core Data支持iCloud。而使用iCloud的App。Apple推荐的可能性增加。

  6. 有了iCloud为以后Apple的全平台数据共享打下基础

所以,没有理由拒绝使用Core Data做为你App的持久化。Core Data应该是一个跟Apple混的第一选择。

存储原理

NSManagedObjectModel

认识

我个人是把NSManagedObjectModel看做为一个core data的schema。生成这个类的来源是xCode中的Data Model

点击之后会生成一个.xcdatamodeld的文件夹里面的数据具体是是用xml来存储的。
但是你在xCode里面看这个.xcdatamodeld文件夹是认为一个文件。然后可以用xCode来进行图形化的编辑。

如这样

当然还有另外一种表格的方式来编辑Data Model

我们编辑这个的这个文件,理论上来说只是一个资源文件。相当于数据库的schema。我们的数据库长什么样子,就是你来设计的。然后在程序中通过NSURL找到这个资源文件的位置。就可以初始化成为NSManagedObjectModel。

代码加载Data Model

当我们设计好我们的Data Model以后。可以用以下代码,把Data Model加载到NSManagedObjectModel里面去。

1
2
3
4
5
6
7
- (void)initializeCoreDataStack
{
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"PPRecipes" withExtension:@"momd"];
    ZAssert(modelURL, @"Failed to find model URL");
    NSManagedObjectModel *mom = nil;
    mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; ZAssert(mom, @"Failed to initialize model");
}

NSPersistentStoreCoordinator这样我们就从main bundle里面把data model加载到NSManagedObjectModel这个类里面去了。

NSPersistentStoreCoordinator是整个Core Data的核心。因为承担着全部数据的持久化,加载数据,缓存数据的工作。可以看做Core Data的心脏。

值得我们开心的事情是,虽然NSPersistentStoreCoordinator很重要,但是我们在写程序的时候其实只用初始化和设置一些很简单的参数就可以使用了。在我们App的整个生命周期里面其实并不会很频繁的使用到它。

初始化NSPersistentStoreCoordinator

初始化NSPersistentStoreCoordinator分为两个步骤

  1. 用已经初始化好的NSManagedObjectModel去初始化它

  2. 选择NSPersistentStore为存储的方式

NSPersistentStore

理论上来说NSPersistentStoreCoordinator的数据不一定要存到硬盘上,它可以存到内存里,可以存到网络上。不过都肯定是对应着不同的应用场景。所以我们一般情况还是把它存储到磁盘上。 NSPersistentStore就是用来描述我们要把数据存到哪里的类。NSPersistentStore还可以指定存储数据的文件的文件类型。

目前知道的NSPersistentStore支持三种类型:

  1. SQLite

  2. 二进制

  3. XML

我就只使用SQLite。理论上来说,NSPersistentStore不管选择什么样的存储文件。你后面进行Core Data的操作都是一样的。并不需要修改你的逻辑代码。这就是Core Data把底层封装了一次的好处。(书上说iOS上不建议使用XML)

有一点需要注意的是NSPersistentStoreCoordinator可以加入不止一个的NSPersistentStore。这个在某些特定场景还是很有用的,以后如果能写到在写把。

代码加载NSPersistentStoreCoordinator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  dispatch_queue_t queue = NULL;
    queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_async(queue, ^{        NSFileManager *fileManager = [NSFileManager defaultManager];        NSArray *directoryArray = [fileManager URLsForDirectory:NSDocumentDirectory
                                                      inDomains:NSUserDomainMask];        NSURL *storeURL = nil;
        storeURL = [directoryArray lastObject];
        storeURL = [storeURL URLByAppendingPathComponent:@"PPRecipes.sqlite"];        NSError *error = nil;
        NSPersistentStore *store = nil;
        store = [psc addPersistentStoreWithType:NSSQLiteStoreType
                               configuration   :nil
                               URL             :storeURL
                               options         :nil
                               error           :&error];        if (!store) {
            ALog(@"Error adding persistent store to coordinator %@\n%@",
                 [error localizedDescription], [error userInfo]);
        }
    });

由于这个过程是一个比较耗费资源的过程。所以我们应该把它放到后台线程里面去做。

1
2
NSFileManager *fileManager = [NSFileManager defaultManager];        NSArray *directoryArray = [fileManager URLsForDirectory:NSDocumentDirectory
                                                      inDomains:NSUserDomainMask];

Apple中不管是OS X还是iOS能上架的App,都是沙箱机制。这个可以自己Goolge看相关的资料。这样的话每一个App都有自己的文件系统。这两句也比较常使用。就是可以获得自己沙箱中的Document文件夹路经。参数的信息直接查文档把。由于这个过程是一个比较耗费资源的过程。所以我们应该把它放到后台线程里面去做。

接下来很重要的一句是

1
2
3
4
5
store = [psc addPersistentStoreWithType:NSSQLiteStoreType
                        configuration   :nil
                        URL             :storeURL
                        options         :nil
                         error           :&error];

第二个参数比较高级。我还没有用到过。文档上写的是设置为nil的时候是把NSPersistentStoreCoordinator作为默认的配置,如果是其他参数可能是把NSPersistentStoreCoordinator设置为其他的用途。此函数的第一个参数是指定NSPersistentStore的存储类型,我们之前说过的三种类型之一。NSSQLiteStoreType就代表这SQLite文件类型。

第三个参数就是我们要存储文件的位置。刚刚我们不是获得的沙箱里面的Document文件夹路经了么。然后我们把文件名加入拼为了一个文件的完整路经传入。

第四个参数类型是一个字典,我们可以传入不同的参数来指定这个NSPersistentStore的类型。比如在本地比如在iCloud。比较高级先为nil。

最后一个参数,为error,传入一个error指针。如果NSPersistentStore初始化失败我们可以获得相应信息。

NSManagedObjectContext

NSManagedObjectContext是我们很经常使用到的一个类。对于为什么要有这个类我个人理解是这样的,在我有限的数据库知识中记得,IO操作是很费时的,因此数据库一般情况是把一系列的操作缓存到了一个内存区域,等待合适的实际在去写入真实的磁盘中。这样大大的提高效率。如果你插入一条数据,然后修改数据,最后删除掉这条数据。如果是每次都执行Commit的话是操作三次IO,如果我们把这三条合并在一起commit的话。是任何事情都不必做。这样能有效的提高整个系统的效率。我认为NSManagedObjectContext的作用在于跟持久化直接做了这层缓存。我们使用Core Data。

还有一点需要注意的是NSManagedObjectContext并不是线程安全的。

关于NSManagedObjectContext的线程安全和高级解释,这里有两篇blog写的超好。

可以一看

Multi-Context CoreData

Zarra on Locking

初级应用的话只用记住一个就ok了NSManagedObjectContext是有一个NSManagedObjectContextConcurrencyType的属性。如果我们是UI操作(主线程操作)我们应该把它设置为NSMainQueueConcurrencyType类型的。

代码加载NSManagedObjectContext

1
2
3
4
5
NSManagedObjectContext                  *moc = nil;
NSManagedObjectContextConcurrencyType   ccType = NSMainQueueConcurrencyType;
moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:ccType];
[moc setPersistentStoreCoordinator:psc];
[self setManagedObjectContext:moc];

总结

至此,三个Core Data的核心类就已经简单说完了一次。他们的关系在上面的图片中表示的很清楚的样子。

NSPersistentStoreCoordinator从NSManagedObjectModel得到模型然后选择NSPersistentStore作为持久化目的地。然后NSManagedObjectContext在作为NSPersistentStoreCoordinator的一个缓存区给我们操作。

当然我这篇blog和接下来准备写的Core Data的可能不会是有完整代码和具体实例的文章。可能只是我对Core Data使用上的一些感悟和梳理。

Core Data (一)备的更多相关文章

  1. Core Data (二)备

    序 上次只是说了三个Core Data栈基本类.这次准备介绍一下常用的类. NSManagedObject Core Data是一次底层数据封装成面向对象的技术.最直接的表现就是在SQLite里面的一 ...

  2. Core Data的使用(二)备

    一.基础概念深入 1.NSManagedObjectContext 被管理数据上下文就像便笺簿 当从数据持久层获取数据时,相当于把这些临时的数据拷贝写在便笺簿上,然后就可以随心所欲的修改这些值. 通过 ...

  3. 使用Core Data应避免的十个错误

    原文:Avoiding Ten Big Mistakes iOS Developers Make with Core Data   http://www.cocoachina.com/applenew ...

  4. iOS开发过程中使用Core Data应避免的十个错误

    原文出处: informit   译文出处:cocoachina Core Data是苹果针对Mac和iOS平台开发的一个框架,主要用来储存数据.对很多开发者来说,Core Data比较容易入手,但很 ...

  5. iOS之Core Data及其线程安全

    一.简介 Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对 ...

  6. Core Data的一些常见用法

    一.简介 Core Data是一个纯粹的面向对象框架,其本质就是一个ORM(对象关系映射:Object Relational Mapping),能以面向对象的方式操作SQLite数据库.在实际开发中绝 ...

  7. Core Data 使用映射模型

    Core Data 使用映射模型 如果新版本的模型存在较复杂的更改,可以创建一个映射模型,通过该模型指定源模型如何映射到目标模型. 创建映射模型,新建File,  Core Data 选择Mappin ...

  8. SELF, self in CORE DATA

    Predicate SELF Represents the object being evaluated. CORE DATA Retrieving Specific Objects If your ...

  9. Core Data浅谈初级入门

    Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象.在此数 ...

随机推荐

  1. KEIL中的变量相关

    例:sfr P0=0x80表示P0口地址为80H:(sfr是字节操作) sfr16 T2=0xCC表示T2口地址的低地址为TL2=0XCC,高地址为TH2=0XCD(sfr16是字操作) 头文件reg ...

  2. OpenUrl 的跨平台实现

    OpenUrl 是 iOS 中 UIApplication 提供的一个函数,用于调用其它程序.实际上各个平台都有自己的实现,这里提供一个直接封装完的跨平台版本给大家.           Delphi ...

  3. 单元测试之C/C++

    如今TDD很火,我公司小,一般写代码不写测试用例的,一般就是随便测试下函数的输入输出,没用工具或框架来测试,非常简单,一点也不正规化. 在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数 ...

  4. ios论坛

    http://developer.cocoachina.com/ 讨论区:http://www.cocoachina.com/bbs/ http://bbs.9ria.com/forum-58-1.h ...

  5. (转载)tarjan求割点

    割点是无向图中去掉后能把图割开的点.dfs时用dfn(u)记录u的访问时间,用low(u)数组记录u和u的子孙能追溯到的最早的节点(dfn值最小).由于无向图的dfs只有回边和树边,且以第一次dfs时 ...

  6. c语言 (linux下)

    生成二进制 : gcc -o hello hello.c 生成汇编:gcc -o hello.s -S hello.c 生成预编译文件:gcc -o hello.i -E hello.c int ma ...

  7. [原创作品] Express 4.x 接收表单数据

    好久没有写博客,从现在开始,将介绍用nodejs进行web开发的介绍.欢迎加群讨论:164858883. 之前的express版本在接收表单数据时,可以统一用res.params['参数名'],但在4 ...

  8. [Err] 1449 - The user specified as a definer ('admin_isbox'@'localhost') does not exist

    晚上加班调用一个远程拷贝的本地Mysql的储存过程,报错:[Err] 1449 - The user specified as a definer ('admin_isbox'@'localhost' ...

  9. 杭电 HDU ACM Milk

    Milk Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  10. EL 表达式中自己定义函数

    第一步: 在WEB-INF/tld/ 文件夹下创建一个func.tld文件例如以下: <taglib xmlns="http://java.sun.com/xml/ns/j2ee&qu ...