序

恩,用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. flex

    http://www.w3.org/html/ig/zh/wiki/Css3-flexbox https://developer.mozilla.org/zh-CN/docs/CSS/CSS_Refe ...

  2. 智能卡 ATR解析

    如果终端不支持IC卡支持的其它传输协议以及传输参数值,IC卡应该有能力用基本ATR定义的模式和终端进行交互. 终端如果无法满足IC卡回送ATR中定义的传输模式,将发送一个热复位信号,或将IC卡置为静止 ...

  3. 关于volatile

    也许读者会注意到,端口寄存器的变量使用了volatile 修饰符,这是因为C语言在编译的时候会进行某种优化来提高效率,比如下面这段代码int i = 1;int a = i;int b = i;对于编 ...

  4. java I/O之装饰者模式

    装饰者: Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案. 装饰者模式意图: 动态的给一个对象添加额外的职责.Decorato ...

  5. BZOJ1662: [Usaco2006 Nov]Round Numbers

    1662: [Usaco2006 Nov]Round Numbers Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 147  Solved: 84[Sub ...

  6. Asp.Net 构架(Http Handler 介绍) - Part.2

    原文地址:http://www.cnblogs.com/JimmyZhang/archive/2007/09/15/894124.html 引言 在 Part.1 Http请求处理流程 一文中,我们了 ...

  7. C#中单问号,双问号的用法(转)

    原文:http://hi.baidu.com/guodong828/blog/item/c78fc23f847314cb7d1e7193.html 单问号---用于给变量设初值的时候,给变量(int类 ...

  8. hdu2769:枚举+同余方程

    题意:有一个随机数生成器  x[i+1]=(a*x[i]+b)%10001 已知  x1,x3,x5...求 x2,x4,x6...... x的个数为 2n (n<=10000) a,b也在 0 ...

  9. shiro内置过滤器研究

    anon org.apache.shiro.web.filter.authc.AnonymousFilter authc org.apache.shiro.web.filter.authc.FormA ...

  10. linux shell在while中用read从键盘输入

    系统是ubuntu 14.04 64bit,之前曾想安装Stream来玩dota2,但最终没成功.由于Stream只有32bit,安装Stream时也安装了大量32bit的库.删除Stream后,这些 ...