Presentation is loading. Please wait.

Presentation is loading. Please wait.

Core Data. 单元目标 Core Data 简介 数据模型映射 Core Data 数据访问 生成实体类代码 Core Data 查询 2.

Similar presentations


Presentation on theme: "Core Data. 单元目标 Core Data 简介 数据模型映射 Core Data 数据访问 生成实体类代码 Core Data 查询 2."— Presentation transcript:

1 Core Data

2 单元目标 Core Data 简介 数据模型映射 Core Data 数据访问 生成实体类代码 Core Data 查询 2

3 Core Data 简介 3

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

5 Core Data 简介 面向对象的程序员大多都不喜欢用基于 C API 去做数据持久化。 希望使用面向对象的编程去持久化数据。 使用 Core Data 是比较好的选择。 它是支持数据库方式,建立对象图。 – 通常使用 SQLite3 它是如何工作的? – 通过可视化的方式建立数据库和对象的映射 – 使用面向对象的 API 来查询对象 – 使用对象属性访问数据库中对应表的列 5

6 数据模型映射

7 如何创建数据模型映射 在 Xcode 里 , Resource 目录下新建文件并选 择 Data Model 7

8 如何创建数据模型映射 可以用已存在的类和它们的属性当作模板 – 但很少这样做,通常从头开始生成对象并映射 – 可以跳过这个窗口 8

9 .xcdatamodel 文件创建 这个文件用于建立对象和数据库的映射, 和.xib 文件类似。 9

10 创建实体 在数据库中实体对应为 “ 表 “ ,在我们的代码 里映射为 ” 对象 ” 。 – 这里 用 Photo 实体来代表照片 10 点击 + 号, 添加 一个实 体 修改实体 名为 Photo 对应实体类型 NSManageObject

11 给实体添加属性 属性映射为数据库的 “ 列 ” ,映射为对象属性 thumbnailURL 用于存储 URL, 使用它下载我们的照片缩略图 11 点击 + 号来 添加 属性 和修改 实体名 一样 属性的类 型 为 ”string”. 对应到代 码里为 NSString

12 属性选项 12 Optional: 对象创建时默认值应许为 空 Transient: 只有在对象端有这个属 性(不存到数据库中) Indexed: 为了提高属性搜索效率

13 增加另一个属性 增加 thumbnailData 属性,用于存储照片缩略图实 际的图片数据 13

14 创建另外一个实体 Photograhper 实体代表谁照了这张照片 14

15 建立两个实体间的关联关系 建立一个 ” 一对多 ” 关联关系 photos – 在对象中映射为 (NSSet *) – 一个摄像师拥有很多照片 15 通过 ”Add Relationship” 来增加关联 关系 关联关系 名称 指向 Photo 对象 它没有 ”inverse” 关系, 它们是 “ To-Many ” 的关联关系

16 双向关联 (inverse 关联关系 ) 在 Photo 实体上,增加 whoTook 关联关系,它指向 Photographer 实体。 whoTook 不是多对一关系,因此它是 NSManagedObject 属性 (而不是 NSSet ) 16 whoTook 是 Photos 的逆向 关联关系 箭头变 成双向

17 Core Data 数据访问

18 关于 Core Data 还有许多其它事情可以做 – 前面部分我们只关心创建实体,属性,关联关系 如何通过程序方式访问数据? – 需要用 NSManagedObjectContext 如何得到 NSManagedObjectContext – 在创建项目时,选择复选框 “User Core Data for storage” – 应用程序 代理 里有一些代码支持 Core Data – 最特别的是代理中有一个属性 ”managedObjectContext” – 正是利用这个对象去访问数据库中,创建或查询对象 18

19 如何创建一个新对象 19 NSEntityDescription 类方法返回一个 NSManagedObject. 所有来自数据库的对象不是 NSManagedObject 就是它的子类 通过传递参数方式来引用 NSManagedObjectContext – 上面的代码通常不是在应用程序代理中 – 不要把应用程序代理当成全局变量 – 所以必须在 API 中传递 NSManagedObjectContext(Controllers 等 ) – 通常,在视图控制器如下方式处理 Core Data 的显示 initInManagedContext: (NSManagedObjectContext *) Context NSManagedObject *photo = [NSEntityDescription insertNewObejectForEntityForName:@”Photo” inManagedObjectContext: (NSManagedObjectContext *) ctxt];

20 如何获得属性值 可以通过以下两个方法来访问 – ( id ) valueForKey: (NSString *)key; – (void) setValue: (id) value forKey:(NSString *)key; key 是对象映射中的属性名 – 如: @”thumbnailURL” value 将被存储到数据库里 – 如果值没有被设置,默认是 nil 。 – 所有的值都是对象 – Binary data 值对应的是 NSData 对象 – “To-many” 映射的关联关系值对应为 NSSet 对象 一切都会为你管理 SQL 自动生成,数据延迟加载等 20

21 如何保存数据 数据修改 ( 写入 ) 都是花生在内存中,除非你 保存 – 任何时候一批数据变化,都应保存 – Save: 是 NSManagedObjectContext 的实例方法 – 保存之前,需要判断对象是否有改变 - ( BOOL ) hasChanges; 典型的代码块 – 所有错误都可以通过 NSError userInfo 来报告 21 -( void) saveChangesToObjectsInMyMOC: (NSManagedObjectContext *) context { NSError *error = nil; if ( [context hasChanges] && ![context save:&error]){ NSLog(@” 错误! %@”,error,[error userInfo] ); abort();// 在这里生成崩溃 log, 用于调试 }

22 生成实体类代码

23 两种 Xcode 生成代码的方式 用我们创建的数据映射描述来创建新的实 体类 “Copy and paste” 方式 23

24 映射描述来创建新的实体类 在 Xcode 选择需要生成代码的实体 24

25 选择新建文件 选择 “Managed Object Class” 作为要创建文 件的类型 25

26 选择存放生成类的项目目录 只要点击 ”Next” 按钮 26

27 选择实体生成类 27

28 对应生成的文件 在 resource 目录下创建了两个文件 (.h,.m) – 为了目录不混乱,最好移到 Classes 目录下 28

29 “Copy and paste” 方式 在以下两种情况下使用 – 如果已经有 NSManagedObject 定制子类文件 – 或许想添加或改变一个属性并且需要代码生成 属性 29

30 30 选择需要生成 代码的属性 Copy 和 paste 生成的代码 到.h 或.m

31 生成的代码.h 只有每一个实体属性对应的 @property 31 #import @interface Photo : NSManagedObject { } @property (nonatomic, retain) NSData * thumbnailData; @property (nonatomic, retain) NSString * thumbnailURL; @property (nonatomic, retain) NSManagedObject * whoTook; @end #import @class Photo; @interface Photographer : NSManagedObject { } @property (nonatomic, retain) NSSet* photos; @end

32 生成的代码.m @dynamic – 使用运行期机制拦截对象消息,在这种情况下, NSManagedObject 使用 valueForKey: 或 setValueForKey: 来 操作属性 – 使用. 记号来访问数据库实体 32 @implementation Photo @dynamic thumbnailData; @dynamic thumbnailURL; @dynamic whoTook; @end Photo *photo = [NSEntityDescription insertNewObjectForEntityForName:@”Photo” inM..] NSString * myThumbnail = photo.thumbnailURL; Photo.thumbnailData = … Photo.whoTook = …/ 一个摄像师对象,可以通过查询语句创建

33 NSFetchRequest 到目前为止,我们可以 – 通过 insertNewObjectForEntityForName:inManagedobjectContext : 来创建持久化 对象 – 通过 valueForKey:/setValueForKey 或 @property 来 访问或改变属性 值 在 Core Data 框架里如何查询数据 – 可以通过执行 NSManagedObjectContext 中的 NSFetchRequest 来获 得查询数据 查询过程中涉及到的四个重要对象 – NSEntityDescription 指定查询那个实体(必须) – NSPredicate 指定获取那些实体对象(可选,默认获得所有对象) – NSSortDescription 指定返回数组的排序方式。(可选,随机的) – 指定一次获取多少对象或最大获取多少个对象。(可选,所有对 象) 33

34 创建 NSFetchRequest 查询代码块 通过实体描述来获取想要的对象 – request.entity = [NSEntityDescription entityForName:@”Photo” inManagedObjectContext:ctxt]; – 通过 NSEntityDescription 来创建实体描述的实例 – 设置获取数据的大小或最大数 34 NSFetchRequest *request = [[NSFetchRequest alloc ] init]; request.entity = [NSEntityDescription entityForName:@”Photo” inManagedObjectContext:ctxt]; request.fetchBatchSize = 20; request.fetchLimit = 100; Request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; Request.predictate = ….;

35 NSSortDescriptor 当执行 fetchRequst 对象时,它将返回一个存 NSManagedObject 对象数组。 数组是 “ 有序的 ” ,因此我们获取数据时通常想指 定顺序。通过给 fetchRequest 一列 “ 排序描述 ” 用它 来描述什么排序方式 也可以不用 selector 参数 (默认使用的方法 compare: ) selector: 参数只是一个方法,它可以对每个关键字 进行相互比较。 35 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@”thumbnailURL” ascending: YES selector: (localizedCaseinsensitiveCompare:)];

36 NSPredicate 如何准确指定那些数据是我们想要从数据 库中获取的呢? predicateWithForm:arguments…. – @”uniqueid == %@,[dept objectForKey:@”id”] – “@ in tags”,(NSMagagedObject *)// tags 是 to-many 的关系 – “viewed > %@”,(NSDate *)// viewed 是日期类型的属性 – @”name contains[c] %@”,(NSString *)// 匹配 name 属性的字 符串,大小些敏感 36 NSString *username =@”davinlei”; NSPredicate *predicate = [NSPredicate predicateWithFormat: @”name contains %@”, username];

37 NSCompoundPredicate 用并且和或的运算方式组合 predicate 条件 37 NSArray * array = [NSArray arrayWithObjects:predicate1,predicate2,nil]; NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:array];

38 综合使用 Photographer 是 NSManagedObject 的子类 通过 photographerWithName 方法从数据库获取一 个 photographer 创建 fechRequest 对象 获取 davinlei 所拍的所有照片 38 NSManagedObject *photographer = [Photographer photographerWithName:@”davinlei” inManagedObjectContext] NSFetchRequest *request = [[NSFethcRequest alloc] init]; request.entity = [NSEntityDescription entityForName:@”Photo” inManagedObjectContext:ctxt]; request.fetchBatchSize = 20; request.soreDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@”title” ascending: YES]; request.predicate = [NSPredicate predicateWithFormat:@”whoTook = %@”,photographer]

39 fetchRequst 实际获得的结果 使用 executeFetchRequest: error 方法 – 如果发生异常,则返回 nil( 详细错误信息查看 NSErro) – 如果没有任何匹配的对象,则返回空数组 – 如果有数据匹配,则返回 NSManagedObjectd 对象数组 – 如果不关心错误信息,可以传 NULL 给 error 参数 遍历结果 39 NSFetchRequest *request = …… NSError **error = nil; NSArray *results = [managedObjectContext executeFetchRequest:request error:&error]; NSManagedObject *photo = [results objectAtIndex:0]; For(Photo *photo in results ){….} Photo *photo = [results lastObject];// 返回 0 或 1 个对象

40 删除对象 如果对象之间有关联关系? – 如: 当删除 photograther 拍的最后一张照片,是否删除 photograther? – 可以在关联控制地方设置 选中 “Createing and Deleting Managed Objects” 40 [managedObjectContext deleteObject (NSManagedObject *) anObject];

41 Question? 41


Download ppt "Core Data. 单元目标 Core Data 简介 数据模型映射 Core Data 数据访问 生成实体类代码 Core Data 查询 2."

Similar presentations


Ads by Google