CoreData编程指南.pdf

上传人:索**** 文档编号:76253647 上传时间:2023-03-08 格式:PDF 页数:13 大小:488.72KB
返回 下载 相关 举报
CoreData编程指南.pdf_第1页
第1页 / 共13页
CoreData编程指南.pdf_第2页
第2页 / 共13页
点击查看更多>>
资源描述

《CoreData编程指南.pdf》由会员分享,可在线阅读,更多相关《CoreData编程指南.pdf(13页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、Core Data 编程指南一、技术概览1.Core Data 功能初窥对于处理诸如对象生命周期管理、对象图管理等日常任务,Core Data 框架提供了广泛且自动化的解决方案。它有以下特性。(注:对象图Object graph 的解释:在面向对象编程中,对象之间有各种关系,例如对象直接引用另外的对象,或是通过引用链间接的引用其他对象,这些关系组成了网状的结构。我们把这些对象(和它们之间的联系)成为对象图。对象图可大可小,有繁有简。只包含单个字符串对象的数组就是一个简单的代表;而包含了application对象,引用 windows,menus 和相关视图对象、其他对象这样的结构就是复杂对象图

2、的例子 这是在说mainwindow.xib。有时,你可能想要把这样的对象图转化形式,让它们可以被保存到文件中,以使其他的进程或其他的机器可以再次将保存的内容读出,重购对象。这样的过程常被成之为“归档”(Archiving)。有些对象图是不完整的 通常称之为局部对象图(partial object graphs)。局部对象图包含了“占位符”(Placeholder)对象,所谓”占位符“,就是一些暂时无内容的对象,它们将再后期被具体化。一个典型的例子就是nib 文件中包含的 Files Owner 对象。1)对于 key-value coding 和 key-value observing 完整

3、且自动化的支持除了为属性整合KVC 和 KVO 的访问方法外,Core Data 还整合了适当的集合访问方法来处理多值关系。2)自动验证属性(property)值Core Data 中的 managed object 扩展了标准的KVC 验证方法,以保证单个的数值在可接受的范围之内,从而使组合的值有意义。(需校准翻译)3)支持跟踪修改和撤销操作对于撤销和重做的功能,除过用基本的文本编辑外,Core Data 还提供内置的管理方式。4)关系的维护Core Data 管理数据的变化传播,包括维护对象间关系的一致性。5)在内存中和界面上分组、过滤、组织数据6)自动支持对象存储在外部数据仓库的功能7)

4、创建复杂请求你不需要动手去写复杂的SQL 语句,就可以创建复杂的数据请求。方法是在“获取请求”(fetch request)中关联 NSPredicate(又看到这个东东了,之前用它做过正则)。NSPrdicate支持基本的功能、相关子查询和其他高级的SQL 特性。它还支持正确的Unicode 编码(不太懂,请高人指点),区域感知查询(据说就是根据区域、语言设置调整查询的行为)、排序和正则表达式。8)延迟操作(原文为Futures(faulting)直译为期货,这里个人感觉就是延迟操作的形象说法。请高人指教)。Core Data 使用延迟加载(lazy loading)的方式减少内存负载。它还

5、支持部分实体化延迟加载,和“写时拷贝”的数据共享机制。(写时拷贝,说的是在复制对象的时候,实际上不生成新的空间,而是让对象共享一块存储区域,在其内容发生改变的时候再分配)。9)合并的策略Core Data 内置了版本跟踪和乐观锁定(optimistic locking)来支持多用户写入冲突的解决。注:乐观锁,假定数据一般不出现冲突,所以在数据提交更新的时候,才对数据的冲突进行检测,如果冲突了,就返回冲突信息。10)数据迁移就开发工作和运行时资源来说,处理数据库架构的改变总是很复杂。Core Data 的 schema migration工具可以简化应对数据库结构变化的任务,而且在某些情况下,允

6、许你执行高效率的数据库原地迁移工作。11)可选择针对程序Controller层的集成,来支持UI 的显示同步Core Data 在 iPhone OS 之上提供 NSFetchedResultsController对象来做相关工作,在Mac OS X 上,我们用Cocoa 提供的绑定(Binding)机制来完成。2.为何要使用Core Data使用 Core Data 有很多原因,其中最简单的一条就是:它能让你为Model 层写的代码的行数减少为原来的50到70%。这归功于之前提到的Core Data 的特性。更妙的是,对于上述特性你也既不用去测试,也不用花功夫去优化。Core Data 拥有

7、成熟的代码,这些代码通过单元测试来保证品质。应用 Core Data 的程序每天被世界上几百万用户使用。通过了几个版本的发布,已经被高度优化。它能利用Model 层的信息和运行时的特性,而不通过程序层的代码实现。除了提供强大的安全支持和错误处理外,它还提供了最优的内存扩展性,可实现有竞争力的解决方案。不使用Core Data 的话,你需要花很长时间来起草自己的方案,解决各种问题,这样做效率不高。除了 Core Data 本身的优点之外,使用它还有其他的好处:它很容易和Mac OS X 系统的 Tool chain 集成;利用 Model 设计工具可以按图形化方式轻松创建数据库的结构;你可以用I

8、nstruments的相关模板来测试Core Data 的效率并 debug。在 Mac OS X 的桌面程序中,Core Data 还和 Interface Builder 集成(打开Inspector可以看到有binding 的选项,这个东东iPhone 上木有。),按照model 来创建 UI 变的更简单了。这些功能能更进一步的帮助你缩短设计、开发、测试程序的周期。3.Core Data 不是。看了前面的介绍之后,我们还需要了解一下关于Core Data 常见的误解:1)Core Data 不是一个关系型数据库,也不是关系型数据库管理系统(RDBMS)。Core Data 为数据变更管理

9、、对象存储、对象读取恢复的功能提供了支持。它可以使用SQLite 作为持久化存储的类型。它本身并不是一个数据库(这点很重要,比如,你可以使用Core Data 来记录数据变更,管理数据,但并不能用它向文件内存储数据)。2)Core Data 不是银弹它并不能取代你写代码的工作。虽然可以纯粹使用XCode 的数据建模工具和Interface Builder 来编写复杂程序,但在更多的程序中,你都自己动手写代码。3)Core Data 并不依赖于Cocoa Bindings Core Data+Cocoa Binding 减少代码数量。但Core Data 完全可以在没有bindings 的条件下

10、使用。例如,可以编写一个没有UI,但包含Core Data 的程序。二、Core Data 基础1.Core Data 基本架构在大部分程序中,你要能通过某种方式打开一个包含对象归档的文件,这个文件内至少要有一个根对象的引用。另外,还得能将所有的对象归档到文件中,如果你想要实现撤销的功能,就还要记录对象的更改情况。例如,在Employee 的示例程序中,你要能打开一个包含有employee和 department对象归档的文件,而且这个文件至少包含了一个根对象 这 里,是一个包含所有employee 的数组 请参考例图Figure 1。相应的,你还要能将程序中的employee、departm

11、ent对象归档到文件中去。Figure 1 按照 Core Data 文档结构管理的对象示意图使用 Core Data 的框架,大多数的功能都可以自动实现,因为我们有managed object context(管理对象的上下文,有时直接叫Context)。managed object context 就像是一个关卡,通过它可以访问框架底层的对象 这些对象的集合我们称之为persistence stack(数据持久栈)。managed object context 作为程序中对象和外部的数据存储的中转站。栈的底部是persistence object stores(持久化数据存储),请看Fig

12、ure 2 的示意图。Figure 2 使用 Core Data 的文档管理示意图Core Data 的使用并不限制在基于文档的程序中(document-based application)。你也能创建一个包含Core Data 的 Utility 程序(请查看Core Data Utility tutorial 文档)。当然其他类型的程序也都可以使用Core Data。被管理对象和上下文(Managed Objects and Contexts)你可以把被管理对象上下文想象成一个”聪明“的便笺簿。当你从数据持久层获取对象时,就把这些临时的数据拷贝拿到写在自己的便笺簿上(当然,在便笺上对象会“

13、恢复”以前的对象图结构)。然后你就可以随心所欲的修改这些值了(本子是你的,随便画都可以),除非你保存这些数据变化,否则持久层的东西是不会变的。(跟修改文件后要保存是一个道理)。附在 Core Data 框架中模型对象(Model objects)常被称为“被管理对象”(Managed objects)。所有的被管理对象都要通过上下文进行注册。使用上下文,你可以在对象图中添加、删除对象,并记录对象的更改(包括单个对象,或是对象间的关系)。记录更改后就能支持撤销和重做的功能。同时,上下文还能保证关系更改后对象图的完整性。如果你想要保存所做的修改,上下文会保证对象的有效性。在验证有效性后,更改会被写

14、入到persistent store(持久化存储层)中。你在程序中的添加和删除动作都会被作用在存储的数据中。在你的一个程序中,可能存在多个上下文。对于数据存储(store)中的每个对象,对应的都有唯一的一个被管理对象(managed object)和上下文相关联(详情请查看Faulting and Uniquing 文档)。换个角度来想,在persistent store中存储的对象有可能被用在不同的上下文中,每个上下文都有与之对应的被管理对象,被管理对象可以被独立的修改,这样就可能在存储时导致数据的不一致。Core Data 提供了许多解决这个问题的途径(请查看Using Managed O

15、bject 一章)。获取数据的请求(Fetch Requests)要使用上下文来获取数据,你需要创建相应的请求(Fetch request)。Fetch request 对象包含你想获取的对象的描述。例如:“所有Employee”,或“所有的 Employee,department是 marketing,按薪资降序排列”。Fetch Request包含三个部分。使用最简单的写法,必须指定实体(Entity)的名称,这就暗示了,每次智能获得一种类型的实体。Fetch Request 还可以包含谓词(predicate)注:有些地方也把这个叫断言,个人感觉谓词更准确些。谓词将描述对象需要满足的条件

16、(这就和我们在SQL 里加的限定条件差不多,正如前面的 All Employees,in the Marketing department)。另外,Fetch Request 还可包含一个用于描述排序方式的对象(熟悉的Order by 操作)。如图Figure3 所示:在程序中,你将Fetch Request 这个请求发送给上下文,上下文就会从相关的数据源中查找复合条件的对象(也可能找不到),并返回。所有的被管理对象(managed object)都必须在上下文中注册,因此通过fetch request 获得的对象自动被注册。但如前所述,每个在持久存储层(persistence store)中

17、的对象都对应一个和上下文相关的被管理对象(managed object),因此,如果在上下文中已经存在了fetch request 要取的对象,那么这个被管理对象将被返回。Core Data 追求高执行效率。它是“需求驱动”的,因此只会创建你确实需要的对象。对象图不需要保留所有在数据存储层中的对象。单纯指定数据持久层的动作不会将其中所有的数据放到上下文中去。当你想从数据存储层中获取某些对象的时候,你只会得到那些你请求的(有点罗嗦,总的意思就是需要时获取,获取的就是需要的)。如果你不在需要这个对象的时候,默认情况下它会被释放。(当然,只是释放这个对象,而不是从对象图中移除该对象)。注:个人感觉有

18、点像重新拷了一个文件的某些部分,不用了就在副本中删除,不会影响原件。持久化存储助理(Persistent Store Coordinator)之前提到过,程序中的对象和外部存储的数据通过Core Data 框架中的一系列对象进行协调,这一系列的对象总的被称为持久存储栈(Persistence stack)。在栈顶是被管理对象上下文(Managed object context),而栈底是持久化对象存储层(Persistence object store)。在它们之间就是持久化存储助理。事实上,持久化存储助理定义了一个栈。从设计方面考虑,它就是可以作为上下文的”外观“,这样多个数据存储(Pers

19、istence store)看起来就像是一个。然后上下文就可以根据这些数据存储来创建对象图了。持久化存储助理智能关联一个被管理对象的模型。如果你像要把不同的实体放到不同的存储中去,就需要为你的模型实体做“分区”,方式是通过定义被管理对象模型的configurations。(请参考 Configurations一章)。Figure 4 演示了这样的一个结构:employees和 departments存储在一个文件中,customers 和 companies存储在另外一个文件中。当你要获取对象的时候,它们从相关的文件中自动获取;当保存时,又被归档到相应的文件中。Figure 4 存储栈 改持久

20、化存储(Persistent Stores)持久化存储是和单独的一个文件或外部的数据关联的,它负责将数据和上下文中的对象进行对应。通常,需要你直接和持久化对象存储打交道的地方,就是指定新的、和程序进行关联的外部数据的位置(例如,当用户打开或保存一个文档)。大多数需要访问持久化存储的动作都由上下文来完成。程序的代码 特别是和被管理对象相关的部分 不应该对持久化存储做任何假设(也就是不需要自己考虑存储的方式或过程)。Core Data 对几种文件格式有原生的支持。你可以选择一种自己程序需要的。假设在某个阶段你决定换一种文件的格式,而又不想修改程序的框架,而且,你的程序做了适当的抽象(注:这个就属于

21、设计方面的东东了),这时,你就能尝到使用Core Data 的甜头了。例如,在最初的设计中,程序只从本地文件中获取数据,而你的程序没有去硬指定对应数据的获取位置,而是可以在后期指定从远程位置添加新的数据类型,这样你就可以使用新的类型,而不需要修改代码。(这段还是感觉翻的不太合适)。重要提示:虽然 Core Dta 支持 SQLite 作为一种存储类型,但它不能使用任意的SQLite 数据库。Core Data 在使用的过程种自己创建这个数据库。(详情,请参考Persistence Store Features)。持久化文档(Persistent Documents)你可以通过代码的方式创建和配

22、置持久存储栈,但在多数情况下,你只是想创建一个基于文档的应用程序(Document-based application,这个是 mac 上的)来读写文件。这时,用NSDocument的子类 NSPersistentDocument可以让你感受到使用 Core Data 的便利。默认状况下,NSPersistentDocument就已经创建了它自己的持久存储栈,其中包含了上下文,和单个的持久对象存储,来处理这样文档和外部数据“一对一”的映射关系。NSPersistentDocument类提供了访问文档的上下文的方法,也实现了标准的NSDocument方法来通过Core Data 读写文件。一般说

23、来,你不需要编写额外的代码来处理对象的持久化。持久化文档的撤销(undo)操作也被集成在被管理对象的上下文中。被管理对象和被管理对象模型(Managed Objects and the Managed Object Model)为 了管理对象图,也为了提供对象持久化的功能,Core Data 需要对对象有很强的描述能力。被管理对象模型就是程序中对象、实体描述的概要图,如图Figure 5 所示。创建模型的常用做法是通过Xcode 的图形化建模工具Date Model Design tool。但是如果你愿意的话,也可以在运行时通过代码来建模。Figure 5 有两个实体的对象模型模型由多个实体描

24、述对象构成,每个描述提供实体的某项元数据,它们包含实体名、实体在程序中的类名(当然,类名和实体名不需要一致)、属性还有关系。属性和关系依次被属性和关系描述对象所代表,如图Figure 6 所示。Figure 6 带有两个属性和一个关系的的实体描述被管理对象必须是NSManagedObject或其子类的实例。NSManagedObject可用来表示任何实体。它使用内部私有的存储机制来维护自身的属性,并执行一个被管理对象所必须的基本操作。一个被管理对象拥有一份实体描述的引用。在使用时,它通过实体描述来找到自身的元数据,包括实体名和属性、关系的信息。你也可以继承NSManagedObject 来执行

25、额外的操作。被管理对象模型(Managed Object Models)多数 Core Data 的功能依赖于你创建的,用来描述程序的实体及其属性、关系的模型图。模型图由NSManagedObjectModel所表示。一般说来,模型的信息越充实,Core Data 能提供的功能就越好。下文讲解了对象模型的特性,以及如何在程序中创建、使用对象模型。被管理对象模型的特性被管理对象模型是NSManagedObjectModel的实例。它描述了你在程序中使用的实体的概要信息。(如果读者不了解 entity、property、attribute 和 relationship的含义,请先查看Core Da

26、ta Basics 和 Cocoa Design Patterns文档中的 Object Modeling 一节)实体(Entities)模型包含了NSEntityDescription对象,NSEntityDescription对象指代了模型的实体。关于实体由两个重要特征:名称(name)和类名(name of class)。你应该弄清楚实体、实体的类和作为实体实例的被管理对象之间的区别。NSEntityDescription 对象可包含NSAttributeDescription对象(指代实体的attribute)和 NSRelationshipDescription 对 象(指代实体间的

27、relationship)。实体也可能包含fetched 属性,该属性由NSFetchedPropertyDescription指代,模型中有对应的fetch 请求的模板,fetch 请求由 NSFetchRequest所指代。实体的继承关系实体的继承和类的继承很类似,当然,也同样有用。如果你有若干个相似的实体,就可以抽离出它们的共有特性作为一个“父实体”,就省去了在多个实体中都指定相同的属性。例如,你可以定义一个包含firstName和 lastName的“Person”实体,然后在定义子实体Employee 和 Customer。如果是使用Xcode 的可视化建模工具来创建模型,你就可以通

28、过如下图的方式为一个实体指定父级实体。Figure1 Xcode 中为一个实体指定父实体如果你想在代码中创建继承关系。就需要自顶向下来执行。不能直接指定实体的父实体,而只能给一个实体指定子实体(使用setSubentities:)。这就是说,如果你想给A 实体指定父实体,就只能把A 作为数组中的一个元素,调用目标父实体setSubentities:的方式来设置。抽象实体你可以把一个实体指定为“抽象实体”,也就是说,你不打算使用这个实体来创建实例。通常,当你想把这个实体作为父实体,而有子实体来实现详细内容的时候,就把它声明“抽象实体”。(和抽象类很像)。例如,在一个绘图程序中,你可能会设计一个G

29、raphic 实体,它包含了x 和 y 坐标信息、颜色、绘制区域,而你不会去创建一个Graphic 的实例,而是使用具体的子实体 Circle、TextArea、Line。(这些基本的东西就不给大牛们再罗嗦了。)Properties(属性,这个和Attributes的意思一样,实在区别不出来,只好上英语了)实体的Properties是它的 attributes和 relationship,包含了 fetched 属性(如果有的话)。每个property 都有名称和 类型。Attribute 也可能有默认值。property 的名称不能和NSObject 和 NSManagedObject类中的

30、无参方法名相同。例如,不能把property 命名为 description。临时属性(Transient Property)也是作为模型的一部分,但是不作为实体实例的数据保存在持久存储层。Core Data 也会跟踪临时属性的变化,以备撤销操作时使用。注意:如果你用模型外的信息对临时属性执行撤销操作,Core Data 将不会使用旧值,调用你的set 方法 它只会更新快照信息(snapshot information)。(这段怪怪的,用到的话在修改一下翻译吧)AttributesCore Data 内部支持各种attribute 的类型,例如string,date,integer(NSStr

31、ing,NSDate,NSNumber)。如果你使用那些不支持的数据,你需要用到在“Non-Standard Persistent Attributes”介绍到的技术。你可以将一个attribute 声明为“可选”(optional),可选的attribute 不 必须有值,但是,不鼓励你将属性置空尤其是数字值(更好的解决方案是使用强制的值,在这里,我们用默认值,例如0)。这样做的原因是为了配合SQL中对于空值NULL 做比较的操作:NULL 不同于 Objective-C中的 nil。数据库中的NULL 不同于 0,搜索 0 值的操作不会匹配到值为NULL 的列。false=(NULL=0)

32、false=(NULL!=0)而且,在数据库中,NULL 也不等于空字符串或是空的数据对象:false=(NULL=)false=(NULL!=)它们之间一点关系都没有。关系(Relationships)Core Data 支持对一、对多的关系,也支持fetched 属性。Fetched property 表示了一种“弱”的、单项的关系。在 employees和 departments的例子中,department 的一个 fetched property 可能是“最近雇佣人”(recent hires),而反过来,employee不会拥有这样的关系。获取数据请求的模板(Fetch Reque

33、st Templates)我们使用NSFetchRequest类来描述数据请求,利用数据请求从持久存储(persistent store)中获取对象。经常需要多次执行同样的请求,或是执行某种模式的请求,但是其中包含可变的元素(如查找条件)这些元素经常有用户提供。例如,在运行的时候,你要根据用户需要获取某个作者在某个指定日期后的出版的所有出版物。你可以预定义请求,把它们作为模板存储在被管理对象模型中。预定义的模板在你需要的时候就可以取出使用。通常情况下,我们通过Xcode 的 data modeling tool 工具创建请求模板。模板可以包含变量,如图Figure 2 所示。Figure 2

34、Xcode predicate builder 关于 Fetch request templates的详细信息,请查看Accessing and Using a Managed Object Model at Runtime 的描述。用户信息字典(User Info Dictionaries)模型中的许多元素,诸如entities,attributes,relationships,都有相关的用户信息字典。用熟悉的键值对,你可以向其中放置任何你需要的数据。这里常用的信息有实体的版本详情,还有针对fetched property,给谓词(predicate)用的值。配置(Configuration

35、s)配置包含了一个名称和若干个相关的实体。实体的集合是可以重叠的 这就是说,一个实体可以出现在多个配置中。在代码中,我们使用setEntities:forConfiguration:的方法来指定配置。也可以用Xcode 的建模工具来指定(选中某个实体,就在属性窗口的第三个,就是一个小扳手的符号)。要获取某项配置的实体,需要用entitiesForConfiguration:的方法。一般说来,如果你想把不同的实体存放在不同的存储中去,就可能用到配置。一个持久化存储助理(persistent store coordinator)只能有一个被管理对象模型。所以,默认情况下,和助理关联的某个存储必须包

36、含同样的实体。要想绕过这个限制,你可以创建一个包含实体子集的模型,然后为每一个子集创建配置,这样一来,使用这个模型创建助理,当你需要添加存储时,可使用不同的配置指定对应的存储属性。当你创建配置的时候,需要记住,不能创建跨存储的关系。使用被管理对象模型通常可以使用Xcode 的建模工具来创建模型(请参考Create a managed object with Xcode)。你也可以全部使用代码来创建(请参考Core Data Utility Tutorial)。编译数据模型数据模型是一种部署资源。在模型中,除了有实体和属性的详细信息外,用Xcode 创建的模型还包含了一些额外的视图信息,包括布局

37、、颜色等等。这些信息在运行时不是必须的。模型文件在编译的过程中会删除这些额外信息以保证尽可能高效的加载。xcdatamodel“源”文件会被 momc 编译器编译为mom 的目标文件。mom 位于/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/,如果你想把它用在自己的build 脚本中,格式是:mom source destination,source 就是 Core Data Model 文件,destination就是输出的mom

38、文件。加载数据模型在一些情况下,你不需要写任何加载模型的代码。如果你使用基于文档的程序框架(Document-based application),NSPersistentDocument会管理诸如查找模型、加载模型的任务。如果你创建了非Document-based application,而且里面又用到了Core Data,一般将获取模型的代码放在application delegate 里。模型的存储名称 也就是文件名,和运行时的名称是不相关的,一旦模型被加载,文件名就没有什么意义了。也就是说,对模型文件,你可以随意命名。如果你想手动加载模型,有两种方式可用,它们各有各的好处:你可以从指定

39、的bundle 集合里创建整合模型,使用如下的类方法:mergeModelFromBundles:也可以用指定的URL 加载单个的模型,使用如下的实例方法:initWithContentsOfURL:(这个方法相信大家都用过)若不需要考虑分开加载模型,第一个类方法很适用。例如:在你的程序中和程序链接的framework 里都有你想要加载的模型。这个类方法可以让你很轻松的加载所有的模型,而不需要考虑模型文件的名称,也不用特定的初始化方法来保证所有的模型都被找到。但是当你有多个模型要加载,特别是这些模型都代表了一个schema 的不同版本,这时,知道要加载哪个模型就很重要了(合并包含相同实体的模型

40、可能导致命名冲突和错误,我们之前“一锅端”的方法不太合适了)。在这种情况下,我们可以用第二个实例方法。另外,有时我们也需要将模型存储在bundle 之外,也需要用这个方法从指定的URL 位置加载模型。还有一点需要说明:我们还有一个类方法modelByMergingModels:可以用。像mergedModelFromBundles:方法一样,它也能合并给定的若干个模型。这样,我们就可以通过URL 来逐一加载模型,然后在创建助理对象之前将它们整合为一个。改变模型由于模型描述了存储层数据的结构,任何改变模型的动作都将使其不在适配于之前创建的存储层。如果你改变了模型的结构,就需要将当前存储层的数据迁

41、移到新版本。(请参考Core Data Model Versioning and Data Migration Programming Guide 文档)。例如:如果你添加了新的实体,或新的属性,你将无法打开旧的存储;如果你添加了验证的限制,或者为属性添加了新的缺省值,你就可以打开旧的存储。在运行时访问和适用被管理对象模型在运行时,被管理对象模型就是一个简单的“对象图”(这个概念之前提到过),认识到这点很重要,尤其是当你需要用代码来访问模型的详细信息时。例如:修改模型(你只能在runtime 之前这样做,请参考NSManagedObjectModel),取回信息(如本地化实体名,属性数据类型,

42、或数据请求模板)。在运行时访问模型有很多方法,通过持久栈最终从持久化存储助理得到模型,代码如下:aManagedObjectContext persistentStoreCoordinatormanagedObjectModel;你也可以通过实体描述得到模型,因此给定一个被管理对象,你就可以得到它的实体描述,进而获得模型。代码如下:aManagedObject entity managedObjectModel;某些情况下,你要维护模型的“直接”引用,也就是说,一个直接返回模型的方法。NSPersistentDocument提供了managedObjectModel方法,可以返回一个模型,该模

43、型和在文档的上下文中使用的持久化存储助理相关联。如果你使用 Core Data Appplication的模板,application delegate 将负责模型的引用。通过代码创建获取数据请求模板(Fetch Request Templates)你可以通过代码创建数据请求模板并将其和模型关联,方法是:setFetchRequestTemplate:forName:如 Listing-1所示。提醒一下:你只能在模型被助理(coordinator)使用之前修改它。Listing 1 通过代码创建获取数据请求模板NSManagedObjectModel*model=;NSFetchRequest

44、*requestTemplate=NSFetchRequest allocinit;NSEntityDescription*publicationEntity=model entitiesByName objectForKey:Publication;requestTemplate setEntity:publicationEntity;NSPredicate*predicateTemplate=NSPredicate predicateWithFormat:(mainAuthor.firstName likecd$FIRST_NAME)AND (mainAuthor.lastName lik

45、ecd$LAST_NAME)AND (publicationDate$DATE);requestTemplate setPredicate:predicateTemplate;model setFetchRequestTemplate:requestTemplate forName:PublicationForAuthorSinceDate;requestTemplate release;访问请求模板你可以用 Accessing and Using a Managed Object Model at Runtime 里介绍的代码片段来获取并使用请求模板。替换字典必须包含和模板中定义的变量对应的

46、键。如果你想测试null 值,必须使用NSNull 对象 参考 Using Predicates。(注:这里的替换字典很好理解,之前的模板中用到了诸如$FIRST_NAME,$LAST_NAME,$DATE 这些东西,就相当于我们在模板中创建好的“变量”,我们需要把一个模板“具体化”,就用替换字典,将里面的变量对应一个值,这里看代码就明白了。)NSManagedObjectModel*model=;NSDictionary*substitutionDictionary=NSDictionary dictionaryWithObjectsAndKeys:Fiona,FIRST_NAME,Verd

47、e,LAST_NAME,NSDate dateWithTimeIntervalSinceNow:-31356000,DATE,nil;/这里的 FIRST_NAME,LAST_NAME,DATE 和我们之前模板里的$FIRST_NAME,$LAST_NAME和$DATE 对应NSFetchRequest*fetchRequest=model fetchRequestFromTemplateWithName:PublicationForAuthorSinceDate substitutionVariables:substitutionDictionary;/从之前的model 中拿出请求模板,然

48、后设定替换字典NSArray*results=aManagedObjectContext executeFetchRequest:fetchRequest error:&error;要是模板里不包含可替换的变量,你要么1.使用 fetchRequestFromTemplateWithName:substitutionVariables:方法,传递nil 给第二个参数或者:2.使用 fetchRequestTemplateForName:并将结果copy。这个方法不需要传递“替换变量”这个参数,但是如果你要用返回值本身,将会有异常抛出(无法在不可变的模型中修改命名的数据请求Cant modify

49、 named fetch request in an immutable model)。本地化被管理对象模型你可以对模型的大部分内容做本地化处理,包括实体和属性名,还有错误信息。要明白,“转成你自己的语言”也是本地化的一部分。即使你不打算提供外语版本,显示“自然语言”的出错提示信息也会有更好的用户体验。例如:“First Name is a required property”就比 firstName is a required property 更好。(后面的这个更像是开发者用的log,显示的是变量名,这里不太明显)。要想对模型进行本地化处理,需要提供一个本地化字典,模式如下:Table 1

50、 针对被管理对象模型的本地化字典键值对应关系:Key Value Note Entity/NonLocalizedEntityName LocalizedEntityName Property/NonLocalizedPropertyName/Entity/EntityName LocalizedPropertyName 1 Property/NonLocalizedPropertyName LocalizedPropertyName ErrorString/NonLocalizedErrorString LocalizedErrorString 备注:(1)在不同实体中的属性,拥有相同的原始

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 技术标书

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com