Managed Object Models(托管对象模型)
Core Data 中大多数功能取决于你所创建的用于描述应用中实体的模型图,以及实体的 properties 和 实体间的 relationships。 模型图是通过 managed object model 表示,managed object model 是NSManagedObjectModel
的实例。一般来说,模型的信息越丰富,Core Data 就能够越好的为你的应用提供服务。本篇文章描述了managed object model的特性以及如果创建并使用 managed object model。
Features of a Managed Object Model(托管对象模型的特征)
managed object model 是NSManagedObjectModel
类的实例。它表示一个模型图,这个模型图是你在应用程序中使用的实体的集合。(如果读者不了解entity、property、 attribute和relationship的含义,请先查看"Core Data Basics"和"Cocoa Design Patterns"文档中的"Object Modeling"一节)
Entities(实体)
managed object model 包含了
NSEntityDescription
对象,
NSEntityDescription
用来指代 managed object model中的实体。实体有两个重要的特征:实体的名称 和 实体对应的类的名称。你必须清楚实体、实体对应的类和实体的托管对象实例 它们之间的区别。
NSEntityDescription
对象可包含 NSAttributeDescription
和NSRelationshipDescription
对象,这两个对象指代模型图中实体的属性。实体也可能包含 fetch 属性,该属性由NSFetchedPropertyDescription
的实例指代,managed object model 可能会有 fetch request 的模板,它由NSFetchRequest
的实例指代。
在一个model中,实体可能会安排在继承层次结构中,实体也可能是抽象的。
Entity Inheritance (实体继承)
实体的继承与类的继承相似。如果你有一些相似的实体,你可以把通用的属性放到父实体中,然后用子实体继承。例如,你定义了一个拥有 firstName 和 lastName 属性的 实体,然后 Employee 实体 和 Customer 实体 就可以继承该实体,继承后就拥有了 firstName 和 lastName 属性。
在许多情况下,你需要实现自定义类用来指代某个实体。你需要将通用业务逻辑放在一个地方,然后供子类继承,而不是在每个实体中都实现一遍。
如果你使用 Xcode 中的 data modeling tool 创建了一个managed object model,你可以在Entity 信息面板的Parent Entity 菜单中选择当前实体的父实体。如图1
图1
如果你在代码中创建继承关系,你必须自定向下的创建。你不能直接设置实体的父实体,你只能设置一个实体的子实体(通过 setSubentities
:)方法。要给一个实体设置父实体,你必须要给父实体设置一个子实体集合,然后再在这个集合中包含这个要设置父实体的实体。
Abstract Entities(抽象实体)
你能够指定一个抽象的实体,这意味着你不会创建该实体的实例。通常,当你有一系列实体用来表示某个通用实体的特殊状态时,那么这个通用实体就不会被实例化。例如,在一个绘画应用中,你可能会拥有一个 图形实体,它定义了x,y坐标,颜色,绘画范围。不过,你永远不会实例化一个图形。具体的图形子实体可能会有 圆形,文本,线。
Properties
一个实体的 property 就是它的 attributes 和 relationships 和 fetched 属性(如果有的话)。每个 property 都有 名称 和 类型。Attributes 可能会有一个默认值。property 的 名称 不能与NSObject
或
NSManagedObject
中的无参方法的名称相同。例如,你不能给 property 的名称设置成 “description”。
临时property也是模型的一部分,但是他们不会被保存到 persistent store 中。Core Data 也会跟踪临时property 的改动,所以,这些属性可以给撤销操作使用。
注意:如果你撤销一个使用了非模型信息的临时property的改动,Core Data 将不会使用旧的数据回调你的 set 方法,只会简单的更新快照信息。
Attributes
Core Data 内部支持多种attribute 类型,例如 string,date,integer (分别对应NSString
,NSDate,NSNumbe)。如果你想要使用的不是原生支持的类型,你可以使用在Non-Standard Persistent Attributes 中介绍的技术。
你能够指定一个 attribute 是可选的,意味着这个attribute不是必须要有一个值。但是,不鼓励这么做,特别是数字值(更好的解决方案是使用强制的值,在这里,我们用默认值,例如0)。这是因为SQL中对NULL的比较和 Objective-C 中的nil不同。NULL
在数据库中和0不同,搜索0将不会匹配到NULL的记录。
false == (NULL == 0)
false == (NULL != 0)
此外,NULL在数据库中与空字符串和空二进制数据也是不同的:
false == (NULL == @"")
false == (NULL != @"")
它们之间没有关系。
Relationships(关系)
Core Data支持对一、对多的关系,也支持fetched属性。 fetched 属性表示了一种“弱”的、单项的关系。 在employees和departments的场景中, department 的一个fetched property可能是“最近雇佣人”(recent hires),而反过来,employee不会拥有这样的关系。Fetch Request Templates (数据检索请求模板)
你能够使用 NSFetchRequest 类描述fetch request,然后利用fetch request 从 persistent store中获取数据。
你可能经常需要在多个场合执行相同的请求或者某种模式的请求,并且请求中包含一些变量(通常由用户提供)。例如,在运行的时候,你要根据用户需要获取某个作者在某个指定日期后的出版的所有出版物。
你可以预定义fetch request 然后作为模板保存到 managed object model中。预定义的模板在你需要的时候就可以取出使用。通常情况下,我们通过Xcode的data modeling tool工具创建请求模板。模板可以包含变量,如图Figure 2所示。
图2
关于Fetch request templates的详细信息,参见"Accessing and Using a Managed Object Model at Runtime"。
User Info Dictionaries(用户字典)
managed object model 中的许多元素例如entity,attributes,relationships都有一个相关的用户字典。你能在用户字典中以键值对的形式存放任何你想放的数据。通常放置在用户字典里的信息有entity版本详情、 fetched property 中 predicate使用的值。Configurations (配置)
配置包含了一个名称和一些相关的entity。entity集合是可以重叠的,意思是一个entity可以出现在多个配置中。通过编程的方式,你可以使用
setEntities:forConfiguration: 方法建立一个配置。
你也可以使用Xcode data modeling tool 建立一个配置(详见
Xcode Tools for Core Data)。可以使用
entitiesForConfiguration:方法获取配置的entity。
通常当你想要把不同的entity存储到不同的存储中去时,你需要使用配置。一个persistent store coordinator只能有一个managed object model,所以,默认情况下,每个和coordinator关联的存储必须包含相同的entity。为了突破这个限制,你可以创建一个包含所有entity集合的 model,然后创建 coordinator时你可以使用这个model。当你往存储中添加数据时,你可以通过配置指定不同的存储属性。当你创建配置的时候,需要记住,不能创建跨存储的关系。