iPhone开发学习笔记——Core Data 框架及运作过程和设计的类





Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂。Core Data相关的类比较多,初学者往往不太容易弄懂。我近期花了一周多时间,才基本入门,今天将一些要点整理出来分享:

一、Core Data 框架的概述

Core Data 是 Cocoa 里面一套非常受欢迎的框架,从 Mac OS X 10.4 提供以来,在 10.5 中引入了完善的schema 迁移机制,再到 iPhone OS 3.0 时被引入 Cocoa Touch,这套完善的框架都被认为是管理大量结构化数据所首选的 Cocoa 框架,尤其是因为使用 Core Data 能大大减少需要手工编写的代码量,就使它更受开发者欢迎了。

不过最近却出现了一些不同的声音,先是传出消息说 Aperture 3.0 抛弃了 Core Data ,改为直接操作 SQLite数据库 (大家联想到 Apple Mail 3.0 也是直接用 SQLite,没有用 Core Data),但因为都是 Apple 内部的决定,大家只能凭空猜测理由;接下来,NetNewsWire 的开发者 Brent Simmons 也说在 NetNewsWire for iPhone 里从 Core Data 转向用 FMDB 来操作 SQLite 数据库 (FMDB 是 Gus Mueller 编写的一层很薄的 SQLite 在 Objective-C 下的封装)Brent 给的理由就很充分了:他要做的很多操作都是对数据批量进行的,其实不需要把所有数据都保存在内存里遍历执行,那样更慢,直接交给数据库,往往一条语句就搞定了,简洁而且快速。

然后 Jonathan “Wolf” Rentzsch 也对此深表赞同 ,并推荐 Aaron Hillegass 的 BNRPersistence 框架,这个框架用Tokyo Cabinet 提供了一个类似 Core Data 接口的数据持久化方案,最大的优点是比 Core Data 快得多,根据Aaron 自己的测试,常见的操作都要快 10 - 20 倍。其实快这么多也可以理解,毕竟 BNRPersistence 要比 Core Data 轻量得多,支持的功能也少很多,加上 Tokyo Cabinet 这样的 Key-value 数据库在处理适合它的操作时,多数要比 SQLite 这样的关系型数据库要快。

所以突然 Core Data 就有点被墙倒众人推的意思,好像以前大家都知道它不好用,但都不好意思说,直到突然有经验足够丰富的开发者开头,就一涌而上开始骂了。我个人的观感是 Core Data 作为官方方案,给开发提供的许多便利还是不可小视的,但考虑学起来确实也不容易 (所以才有人专门写本书讲 Core Data ),所以新上手的Cocoa 程序员不妨先考虑一下 BNRPersistence, FMDB 这样的方案。

那是否 Core Data 就该被抛弃呢?目前的争议其实有点像 Web 开发里到底该不该用 ORM , 区别是大多数Web 开发者因为历史原因,对直接进行数据库操作有偏好 (或者说,本能地反感 ORM),而多数 Cocoa 开发者则坚定支持用对象操作数据,所以长远来看,数据持久化方案在 Cocoa (Touch) 开发里少不了,唯一的疑问是 Apple会不会继续改进 Core Data 的性能和接口,以拉近与第三方方案的差距,只要 Apple 还在不断改进,Core Data 就有学习的必要。

我个人对 Core Data 的怨念主要是在要写的“胶水代码”上:有的时候为了方便与界面的 bindings 操作,不得不给 Model 写大量重复的胶水代码,所以如果第三方的方案如果在这方面有简化,我很乐意改用。

 

二、Core DataSQLite数据库

并非严格的说, CoreData是对SQLite数据库的一个封装。

在苹果iPhoneiPad上,你可以存放数据在以下三个地方

其一是:一个或多个文件

其二是:应用的属性列表(NSUserDefaults

其三是:内置的数据库(SQLite

通常SQLite数据库操作的基本流程是, 创建数据库, 再通过定义一些字段来定义表格结构, 可以利用sql语句向表格中插入记录, 删除记录, 修改记录, 表格之间也可以建立联系。

这个过程出现了, 表格的结构(schema), 所有表格的结构和相互联系构成整个数据库的模型, 数据库存放的方式(可以是文件或者在内存), 数据库操作, sql语句(主要是查询), 表格里面的记录,下面将上面说的文字,CoreData的类作个对应:

SQLite数据库操作

VS

CoreData的类

表格结构

-->

NSEntityDescription

数据库中所有表格和他们的联系

-->

NSManagedObjectModel

数据库存放方式

-->

NSPersistentStoreCoordinator

数据库操作

-->

NSManagedObjectContext

查询语句

-->

NSFetchRequest

表格的记录

-->

NSManagedObject

可能上面的对应关系并非十分严格, 但确实可以帮助理解.

 

下面再看看CoreData的类

首先是NSEntityDescriptionNSManagedObjectModel这两个非常重要的类

NSEntityDescription用来定义表格结构,所以你就可以理解NSManagedObjectModel中的setEntities:(NSArray *)entities函数大概有什么用了,通常, 定义model,是用文件CoreData.xcdatamodel, 可以图形化的操作. 这类似用nib来创建界面。

例如:建个工程, 使用core  data, 模拟器运行之后, 程序对应的document目录出现一个CoreData.sqlite. 可以利用sqlite3命令来查看里面的表格结构:

用命令行sqlite3 CoreData.sqlite 进入

>.tables

ZEVENT        Z_METADATA    Z_PRIMARYKEY

可以看到有表格ZEVENT, 对应的CoreData.xcdatamodel文件有名字叫EventEntity

 

>.schema ZEVENT

CREATE TABLE ZEVENT ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZTIMESTAMP TIMESTAMP )

对应的Event中有属性timeStamp, 可以看到, 相应的ZEVENT表格中有字段TIMESTAMP

 

> select * from ZEVENT

1|1|1|306295807.974966

2|1|1|306295810.981875

3|1|1|306295811.982537

这表格有三个记录, 可以用来初始化三个NSManagedObject, 修改了NSManagedObject, save之后也修改了表格记录。

你可以在CoreData.xcdatamodel添加新的entity, 之后用sqlit3命令来查看数据库的变化。

三、深入认识Core Data 框架

下面先给出一张类关系图,让我们对它有个总体的认识。


在上图中,我们可以看到有五个相关模块:

    1、被管理对象模型(Managed Object Models)

    Managed Object Model 是描述应用程序的数据模型,这个模型包含实体(Entity),特性(Property),读取请求(Fetch Request)等。多数Core Data的功能依赖于你创建的,用来描述程序的实体及其属性、关系的模型图。

    2、被管理对象和上下文(Managed Objects and Contexts)

Managed Object Context 参与对数据对象进行各种操作的全过程,并监测数据对象的变化,以提供对undo/redo 的支持及更新绑定到数据的 UI。使用Core Data的框架,大多数的功能都可以自动实现,因为我们有managed object context(管理对象的上下文,有时直接叫"Context")。managed object context就像是一个关卡,通过它可以访问框架底层的对象——这些对象的集合我们称之为"persistence stack"(数据持久栈)。 managed object context作为程序中对象和外部的数据存储的中转站。栈的底部是persistence object stores(持久化数据存储)

    3、持久化存储助理(Persistent Store Coordinator)

Persistent Store Coordinator 相当于数据文件管理器,处理底层的对数据文件的读取与写入。一般我们无需与它打交道。之前提到过,程序中的对象和外部存储的数据通过Core Data框架中的一系列对象进行协调,这一系列的对象总的被称为持久存储栈(Persistence stack)。在栈顶是被管理对象上下文(Managed object context),而栈底是持久化对象存储层(Persistence object store)。在它们之间就是持久化存储助理。

    4、数据对象(Managed Object ——MO)

    Managed Object 数据对象,与 Managed Object Context 相关联。

    5、控制器Controller

    图中绿色的 Array Controller, Object Controller, Tree Controller 这些控制器,一般都是通过control+drag 将 Managed Object Context 绑定到它们,这样我们就可以在 nib 中可视化地操作数据。

这些模块是怎样运作的呢?

1、应用程序先创建或读取模型文件(后缀为xcdatamodeld)生成 NSManagedObjectModel 对象。Document应用程序是一般是通过 NSDocument 或其子类 NSPersistentDocument)从模型文件(后缀为xcdatamodeld)读取。

2、然后生成 NSManagedObjectContext 和 NSPersistentStoreCoordinator 对象,前者对用户透明地调用后者对数据文件进行读写。

3NSPersistentStoreCoordinator 负责从数据文件(xml, sqlite,二进制文件等)中读取数据生成 Managed Object,或保存 Managed Object 写入数据文件。

4NSManagedObjectContext 参与对数据进行各种操作的整个过程,它持有 Managed Object。我们通过它来监测 Managed Object。监测数据对象有两个作用:支持 undo/redo 以及数据绑定。这个类是最常被用到的。

5Array Controller, Object Controller, Tree Controller 这些控制器一般与NSManagedObjectContext 关联,因此我们可以通过它们在 nib 中可视化地操作数据对象。

四、Model class

模型有点像数据库的表结构,里面包含 Entry, 实体又包含三种 PropertyAttribute(属性),RelationShip(关系), Fetched Property(读取属性)。Model class 的名字多以 "Description" 结尾。我们可以看出:模型就是描述数据类型以及其关系的。

主要的 Model class 有:

Model Classes

Managed Object Model

NSManagedObjectModel

数据模型

Entity

NSEntityDescription

抽象数据类型,相当于数据库中的

Property

NSPropertyDescription

Entity 特性,相当于数据库表中的一列

  > Attribute

NSAttributeDescription

基本数值型属性(如Int16, BOOL, Date等类型的属性)

  > Relationship

NSRelationshipDescription

属性之间的关系

  > Fetched Property

NSFetchedPropertyDescription

查询属性(相当于数据库中的查询语句)

 

1Entity - NSEntityDescription

Entity 相当于数据库中的一个表,它描述一种抽象数据类型,其对应的类为 NSManagedObject 或其子类。

NSEntityDescription 常用方法:

+insertNewObjectForEntityForName:inManagedObjectContext: //工厂方法,根据给定的 Entity 描述,生成相应的 NSManagedObject 对象,并插入 ManagedObjectContext 中。

-managedObjectClassName //返回映射到 Entity 的 NSManagedObject 类名

-attributesByName //以名字为 key, 返回 Entity 中对应的 Attributes

-relationshipsByName //以名字为 key, 返回 Entity 中对应的 Relationships

 

2Property – NSPropertyDescription

Property 为 Entity 的特性,它相当于数据库表中的一列,或者 XML 文件中的 value-key 对中的 key。它可以描述实体数据属性(Attribute)Entity之间的关系(RelationShip),或查询属性(Fetched Property)

 

 > Attribute - NSAttributeDescription

Attribute 存储基本数据,如 NSString, NSNumber or NSDate 等。它可以有默认值,也可以使用正则表达式或其他条件对其值进行限定。一个属性可以是 optional 的。

 

 > Relationship - NSRelationshipDescriptio

Relationship 描述 EntityProperty 之间的关系,可以是一对一,也可以是一对多的关系。 

 

 > Fetched Property - NSFetchedPropertyDescription

Fetched Property 根据查询谓词返回指定 Entity 的符合条件的数据对象。

上面说的比较抽象,举个例子来说,见图:

   我们有一个 CocoaDataDemo.xcdatamodeld 模型文件,应用程序根据它生成一个 NSManagedObjectModel对象,这个模型有三个 Entity,每个 Entity 又可包含 Attribute 、RelationshipFeteched Property 三种类型的 Property。在本例中, Author Entity 包含两个Attribute : name 和 email,它们对于的运行时类均为 NSManagedObject;还包含一个与 Post 的 Relationship;没有设置Feteched Property访问属性。

我们通常使用 KVC 机制来访问 Property。下面来看代码:

[代码]c#/cpp/oc代码:

1 NSManagedObjectContext * context = [[NSApp delegate] managedObjectContext]; 
2 NSManagedObject        * author  = nil; 
3        
4 author = [NSEntityDescription insertNewObjectForEntityForName: @"Author" inManagedObjectContext: context]; 
5 [author setValue: @"nemo@pixar.com" forKey: @"email"]; 
6  
7 NSLog (@"The Author's email is: %@", [author valueForKey:@"email"]);

 在上面代码中,我们先取得 NSManagedObjectContext,然后调用 NSEntityDescription 的方法,以 Author 为实体模型,生成对应的 NSManagedObject 对象,插入 NSManagedObjectContext 中,然后给这个对象设置特性 email的值。

    五、运行时——类与对象

> Managed Object – NSManagedObject

Managed Object 表示数据文件中的一条记录,每一个 Managed Object 在内存中对应 Entity 的一个数据表示。Managed Object 的成员为 Entity 的 Property 所描述。

比如在上面的代码,author 这个 NSManagedObject,对应名为 Author 的 Entity

 

每一个 Managed Object 都有一个全局 ID(类型为:NSManagedObjectID)。Managed Object 会附加到一个Managed Object Context,我们可以通过这个全局 ID 在 Managed Object Context 查询对应的 Managed Object

NSManagedObject 常用方法

-entity

获取其 Entity

-objectID

获取其 Managed Object ID

-valueForKey:

获取指定 Property 的值

-setValue: forKey:

设定指定 Property 的值

> Managed Object Context – NSManagedObjectContext

Managed Object Context 作用相当重要,对数据对象进行的操作都与它有关。当创建一个数据对象并插入Managed Object Context 中,Managed Object Context 就开始跟踪这个数据对象的一切变动,并在合适的时候提供对 undo/redo 的支持,或调用 Persistent Store Coordinato 将变化保存到数据文件中去。

通常我们将 controller 类(如:NSArrayControllerNSTreeController)或其子类 Managed Object Context 绑定,(如何绑定?后有介绍)这样就方便我们动态地生成,获取数据对象等。

NSManagedObjectContext 常用方法

-save:

将数据对象保存到数据文件

-objectWithID:

查询指定 Managed Object ID 的数据对象

-deleteObject:

将一个数据对象标记为删除,但是要等到 Context 提交更改时才真正删除数据对象

-undo

回滚最后一步操作,这是对undo/redo 的支持

-lock

加锁,常用于多线程以及创建事务。同类接口还有:-unlock and -tryLock

-rollback

还原数据文件内容

-reset

清除缓存的 Managed Objects。只应当在添加或删除 Persistent Stores 时使用

-undoManager

返回当前 Context 所使用的 NSUndoManager

-assignObject: toPersistantStore:

由于 Context 可以管理从不同数据文件而来的数据对象,这个接口的作用就是指定数据对象的存储数据文件(通过指定 PersistantStore 实现)

-executeFetchRequest: error:

执行 Fetch Request 并返回所有匹配的数据对象

 

> Persistent Store Coordinator - NSPersistentStoreCoordinator

使用 Core Data document 类型的应用程序,通常会从磁盘上的数据文中中读取或存储数据,这写底层的读写就由 Persistent Store Coordinator 来处理。一般我们无需与它直接打交道来读写文件,Managed Object Context 在背后已经为我们调用 Persistent Store Coordinator 做了这部分工作。

NSPersistentStoreCoordinator 常用方法

-addPersistentStoreForURL:configuration:URL:options:error:

装载数据存储,对应的卸载数据存储的接口为 -removePersistentStore:error:

-migratePersistentStore:toURL:options:withType:error:

迁移数据存储,效果与 "save as"相似,但是操作成功后,迁移前的数据存储不可再使用

-managedObjectIDForURIRepresentation:

返回给定 URL所指示的数据存储的 object id,如果找不到匹配的数据存储则返回 nil

-persistentStoreForURL:

返回指定路径的 Persistent Store

-URLForPersistentStore:

返回指定 Persistent Store 的存储路径

 

> Persistent Document - NSPersistentDocument

NSPersistentDocument 是 NSDocument 的子类。 multi-document Core Data 应用程序使用它来简化对Core Data 的操作。通常使用 NSPersistentDocument 的默认实现就足够了,它从 Info.plist 中读取Document types 信息来决定数据的存储格式(xml,sqlite, binary)。

NSPersistentDocument 常用方法

-managedObjectContext

返回文档的 Managed Object Context,在多文档应用程序中,每个文档都有自己的 Context

-managedObjectModel

返回文档的 Managed Object Model

 

   六、Fetch Requests

Fetch Requests 相当于一个查询语句,你必须指定要查询的 Entity。我们通过 Fetch Requests 向Managed Object Context 查询符合条件的数据对象,以 NSArray 形式返回查询结果,如果我们没有设置任何查询条件,则返回该 Entity 的所有数据对象。我们可以使用谓词来设置查询条件,通常会将常用的 Fetch Requests 保存到 dictionary 以重复利用。

NSFetchRequest 常用方法

-setEntity:

设置你要查询的数据对象的类型(Entity

-setPredicate:

设置查询条件

-setFetchLimit:

设置最大查询对象数目

-setSortDescriptors:

设置查询结果的排序方法

-setAffectedStores:

设置可以在哪些数据存储中查询


[代码]c#/cpp/oc代码:

01 NSManagedObjectContext * context  = [[NSApp delegate] managedObjectContext]; 
02 NSManagedObjectModel   * model    = [[NSApp delegate] managedObjectModel]; 
03 NSDictionary           * entities = [model entitiesByName]; 
04 NSEntityDescription    * entity   = [entities valueForKey:@"Post"]; 
05     
06 NSPredicate * predicate; 
07 predicate = [NSPredicate predicateWithFormat:@"creationDate > %@", date]; 
08   
09 NSSortDescriptor * sort = [[NSortDescriptor alloc] initWithKey:@"title"]; 
10 NSArray * sortDescriptors = [NSArray arrayWithObject: sort]; 
11   
12 NSFetchRequest * fetch = [[NSFetchRequest alloc] init]; 
13 [fetch setEntity: entity]; //设置你要查询的数据对象的类型(Entity)
14 [fetch setPredicate: predicate]; //设置查询条件
15 [fetch setSortDescriptors: sortDescriptors]; // 设置查询结果的排序方法
16    
17 NSArray * results = [context executeFetchRequest:fetch error:nil]; 
18 [sort release]; 
19 [fetch release];

    在上面代码中,我们查询在指定日期之后创建的 post,并将查询结果按照 title 排序返回。

 

参考资料:

Core Data Reference API listing for the Core Data classes

http://developer.apple.com/documentation/Cocoa/Reference/CoreData_ObjC/index.html

 

NSPredicate Reference API listing for NSPredicate

http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSPredicate.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Head First iPhone and iPad Development》是一本非常受欢迎的iOS开发入门书籍,由Dan Pilone和Tracey Pilone合作撰写。本书以互动方式、富有趣味性和易理解的方式,引导读者逐步学习如何开发iPhone和iPad应用程序。 本书深入浅出地解释了iOS开发的必备知识,包括Xcode工具、Objective-C语言和iOS SDK等。读者将学会如何使用Interface Builder创建用户界面,使用UIKit框架开发应用程序,并使用核心数据管理对象(Core Data)进行数据持久化。 本书的独特之处在于其采用了“大脑友好学习法”(Head First Learning)的理念,通过丰富的图表、练习和案例研究,帮助读者更好地掌握开发技巧。此外,还有趣味的漫画和幽默的插图增加了阅读的趣味性,使学习过程更加轻松愉快。 无论读者是初学者还是有一定开发经验的开发者,都能从此书中受益匪浅。对于没有编程经验的读者来说,本书提供了基础知识,帮助他们逐步掌握开发技能。对于有经验的开发者来说,本书提供了更深入的指导和实践案例,帮助他们提升开发水平。 总之,《Head First iPhone and iPad Development》是一本非常实用和易学的iOS开发入门指南,深受iOS开发者喜爱。无论你是初学者还是有一定经验的开发者,都值得一读。 ### 回答2: 《Head First iPhone and iPad Development》是一本介绍iPhone和iPad开发的书籍,它采用了Head First系列独特的学习方法和语言,为读者提供了一种有趣而易懂的学习体验。 这本书的中文版是采用高清扫描的形式呈现给读者的。通过高清扫描,读者可以清晰地看到书中的文字、图表和代码示例,确保读者获得最好的阅读体验。 《Head First iPhone and iPad Development》详细介绍了iPhone和iPad应用程序开发的各个方面,包括基本的应用程序结构、用户界面设计、图形和动画效果、数据存储和网络连接、多媒体功能等。读者可以通过学习书中的案例和实践项目,逐步掌握iOS开发的基本知识和技能。 与传统的技术书籍不同,《Head First iPhone and iPad Development》以一种轻松、幽默和互动的方式呈现内容,使用了大量的图表、插图和例子来帮助读者更好地理解和记忆概念。这使得学习过程更加有趣,并且有助于读者更好地应用所学知识。 总之,对于想要学习iPhone和iPad开发的人来说,《Head First iPhone and iPad Development》是一本值得阅读的书籍,而中文版的高清扫描更是使得读者能够清晰地获取书中的信息,提升学习效果,享受学习的乐趣。 ### 回答3: 《Head First iPhone开发》是一本介绍iPhone和iPad开发的书籍,采用了头脑风暴的学习方式。该书的中文版也有高清扫描版可供阅读。 这本书以通俗易懂的方式,向读者介绍了iPhone和iPad应用的开发过程。通过大量的示例和演示,读者可以学习到如何使用Objective-C编程语言和iOS开发工具,以及如何构建和设计自己的应用程序。 《Head First iPhone开发》从入门级别开始,逐步引导读者了解Xcode和Interface Builder开发工具的使用方法,让读者能够实践建立自己的应用程序。该书注重实践,通过项目驱动教学,读者可以在实际操作中学习开发的各个方面,如视图、界面元素、多线程、数据存储和网络通信等。 这本书的中文版也提供了高清扫描版,这意味着读者可以清晰地阅读书中的内容和示例代码。这样的好处是读者可以更好地理解书中的概念和技术,并能够更加顺利地跟随书中的教程进行实践。 总而言之,如果你对iPhone和iPad应用开发的基础知识感兴趣,那么《Head First iPhone开发》是一本很好的选择。它通过生动有趣的方式,帮助读者快速入门并掌握开发的技能,同时提供高清扫描版的中文版,方便读者清晰阅读和理解内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值