创建一个托管对象模型
Core Data 的许多功能取决于您创建的模式来描述应用程序的实体,它们的属性以及它们之间的关系。Core Data 使用称为托管对象模型的模式 - NSManagedObjectModel
的一个实例。一般来说,模型越丰富,Core Data就能够更好支持您的应用程序。
托管对象模型允许Core Data从持久性存储中的记录映射到您在应用程序中使用的托管对象。该模型是实体描述对象(NSEntityDescription
的实例)的集合。实体描述根据名称,用于在应用程序中表示实体的类的名称以及它具有的属性(属性和关系)来描述实体(您可以将其视为数据库中的表)。
创建一个实体及其属性
当您在Xcode中启动一个新项目并打开模板选择对话框时,选择使用Core Data复选框。Core Data 模型的源文件被创建为模板的一部分。该源文件将具有扩展名.xcdatamodeld
。在导航区中选择该文件以显示核心数据模型编辑器。
要创建一个实体
点击添加实体。
导航区域(navigator area)的实体列表中会出现一个新的无标题实体。
选择新的无标题实体。
在数据模型检查器(Data Model inspector)的实体窗格中,输入实体的名称(name of the entity),然后按回车键。
为实体创建属性和关系
选择新实体后,单击相应部分底部的添加按钮(+)。
在编辑器区域的“属性”或“关系”部分添加新的无标题属性(attribute)或关系(通常称为属性(property))。
选择新的无标题属性。
属性设置显示在“数据模型”检查器的“关系”窗格或“属性”窗格中。
给该属性一个名称,然后按回车键。
属性或关系信息出现在编辑器区域中。
图2-1 Xcode数据模型编辑器中的Employee实体:此时您已在模型中创建了一个实体,但尚未创建任何数据。数据在您启动应用程序稍后创建。这些实体将在您的应用程序中用作创建托管对象(
NSManagedObject
实例)的基础。
定义一个实体
现在您已命名实体,您可以在数据模型检查器的“实体”窗格中进一步定义它;
图2-2 数据模型检查器中的实体窗格
实体名称和类名称
注意,实体名称和类名(NSManagedObject
的子类)不相同。数据模型中的实体结构不需要与类层次结构匹配。图2-2显示了带有推荐的Objective-C类名称模式的类名,伴随MO后缀。实体名称和类名是必需的。
抽象实体
如果您不创建该实体的任何实例,请指定该实体是抽象的。如果您有许多实体都代表特殊化(继承自)一个本身不应该实例化的公共实体,那么通常会进行实体抽象。例如,在Employee实体中,您可以将Person定义为抽象实体,并指定只能实例化具体子实体(Employee和Customer)。通过在数据模型检查器的实体窗格中将实体标记为抽象,您将通知 Core Data它将永远不会直接实例化。
实体继承
实体继承以类继承的方式工作;并且由于相同的原因是有用的。如果您有许多相似的实体,则可以将常见属性归为一个超级实体,也称为父实体。您可以在一个实体中定义它们,而不是在多个实体中指定相同的属性,并且子实体继承它们。图2-3显示了这种布局的一个例子。通过单击右下角的编辑器样式按钮来显示布局图。
在许多情况下,您还实现了一个自定义类,以对应于表示子实体的类也继承的实体。多次实现所有实体通用的业务逻辑,而不是实现它们在一个地方,它们由子类继承。
注意:
使用SQLite持久性存储时,请小心实体继承。所有从另一个实体继承的实体都存在于SQLite的同一个表中。SQLite持久存储设计中的这个因素可能会导致性能问题。
图2-3实体继承图
定义属性(Attributes)和关系
一个实体的属性(properties)是它的特性(attributes)和关系,包括它提取的属性(如果有的话)。在其他功能中,每个属性(properties)都有一个名称和一个类型。属性名称不能与NSObject
或NSManagedObject
的任何非参数方法名称相同 - 例如,你不能给一个属性名称“description”。
瞬态属性(Transient attributes)是作为模型的一部分定义的属性,但不作为实体实例的数据的一部分保存到持久性存储中。Core Data 会跟踪您对瞬态属性所做的更改,因此它们将记录为撤消操作。您可以为了多种目的使用瞬态属性,包括保留计算值和派生值。
注意
如果撤消对使用非建模信息的瞬态属性的更改,Core Data不会使用旧值调用您的set访问器 - 它只是更新快照信息。
图2-4 数据模型检查器中的属性窗格:
属性(Attributes)
要定义一个属性,请在Core Data模型编辑器中选择它,并在Core Data模型检查器的属性窗格中指定值;Core Data本身支持多种属性类型,如字符串,日期和整数(分别表示为NSString
,NSDate
和NSNumber
的实例)。
您可以指定一个属性是可选的 - 也就是说,它不需要有值。但是,一般来说,避免这样做,特别是对于数值。通常情况下,您可以使用具有默认值的强制属性(在属性中为0定义)获得更好的结果。其原因是SQL对NULL有特殊的比较行为,这与Objective-C的nil不同。数据库中的NULL与0不同,并且搜索0不匹配具有NULL的列。而且,数据库中的NULL不等于空字符串或空数据blob。
关系和获取的属性(Properties)
要定义关系,请在 Core Data 模型编辑器中选择它,并在数据模型检查器的关系窗格中指定值;
图2-5数据模型检查器中的关系窗格:
核心数据支持一对多和多对多关系以及获取的属性(fetched properties)。获取的属性表示弱的单向关系。在employees和departments领域,department的获取属性可能是“最近雇用的”(员工与最近的雇用关系不相反)。
“类型”弹出式菜单定义关系是一对一关系还是多对多关系。关系是一次从一个方向定义的。要创建多对多关系,您需要创建两个一对多关系,然后将它们设置为彼此相反的关系。