Creating a Managed Object Model
- 你创建的用于描述应用实例的图表(schema),它们的特性、图表和图表之间的关系,决定了Core Data的功能。Core Data使用图表(schema)告诉管理模型(managed object model)--- (一个管理实例为NSManagedObjectModel)。一般来说,模型越丰富,Core Data越能为应用提供好的支持。
- 在你的应用中,管理数据模型(A managed object model)允许Core Data 从本地储存中映射出数据对象来管理。这是一个收集了实体描述(entity description)对象(objects)的模型(例:NSEntityDesecription)。这个实体描述(entity description)描述了一个实体(你可以把它看做数据库中的一个表格)就它的名字而言。它的名字用于表示在应用程序中实体的类的名称,以及它有什么属性(属性和关系)。
创建实体及属性(Creating an Entity and Its Properties)
- 当你打开Xcode新建一个项目打开模板选择对话框的时候,选择使用Core Data 的复选框(Use Core Data)。Core Data数据模型的源文件就成为了模板的一部分,源文件的后缀名为 .xcdatamodeld。选中Core Data的源文件(.xcdatamodeld后缀的文件)在导航区域选择Editor可以编辑源文件。
创建一个Entity(To create an entity)
1.点击Add Entity(一个新的未命名的Entity出现在导航区实体列表)
2.选择新的未命名的Entity
3.在Entity的“数据模型检查窗口”,输入Entity的名字,然后按回车。
为Entity创建属性和关系(To creat attributes and relationships for the entity)
1.选中新创建的Entity,点击加号按钮(+),一个新的Attributes或者Relationships就被添加在了对应的区域
2.选中新创建的属性(属性的设置就展示在数据模型的Attribute或者Relationships的窗口中)
3.给属性一个名称,按回车键完成。
实体名称和类的名称(Entity name and Class name)
注意:Entity的名字和Class的名字(NSManagedObject的一个子类)并不相同,Entity的结构在数据模型中不需要和类的层次相适应。但是Entity的名字和Class的名字必须要有。(下图例子中Class后面加了一个MO的后缀,我们创建出来Entity的时候,默认Class的名字是相同与Entity的)
(个人理解:Entity和Class并不是一个东西,所以名称可以设置成不同的名字,但是在使用的时候,如果为了方便也可以设置成相同的名字。好比两个人都叫张三,但是不是同一个人)
原文:Note that the entity name and the class name (a subclass of NSManagedObject) are not the same. The entity structure in the data model does not need to match the class hierarchy. Figure 2-2 shows a class name with the recommended class name pattern of Objective-C, along with an MO suffix. An entity name and a class name are required.
抽象实体(Abstract Entities)
如果不创建该Entity的任何实例,则指定的Entity是抽象的。如果你有一个或多个Entity有着相同的部分,那么就可以让一个Entity抽象话,并不需要实例化,然后让有着相同部分的Entity继承这个抽象话的Entity。
实体继承(Entity Inheritance)
Entity的继承工作方式(原理)类似类的继承工作方式(原理),相同的工作原理是有用的。如果你有许多Entity有着相似的地方,那么你就可以把相同属性(properties)包含在一个“超实体”(super Entity,类似class里的超类、父类),也可以成为“父实体”里。这么做要比定义几个相同特性的实体方便,你可以在一个实体里面定义,然后继承。
例:Employee继承Person (注:官方文档的描述和官方配图好像有点不太一样。)
原文:Entity inheritance works in a similar way to class inheritance; and is useful for the same reasons. If you have a number of entities that are similar, you can factor the common properties into a superentity, also known as a parent entity. Rather than specifying the same properties in several entities, you can define them in one entity, and the subentities inherit them. For example, you might define a Person entity with attributes firstName and lastName, and subentities Employee and Customer, which inherit those attributes. An example of this layout is shown in Figure 2-3. Display the layout diagram by clicking the Editor Style buttons in the lower-right corner.
原图:
在许多情况下,你还可以自定义一个类,相当于代表实体类继承的那个实体。与其多次对所有实体共同执行逻辑操作,不如在一个地方实现它们并且由子类继承。
注意
使用SQLite数据持久化时当心Entity的继承,所有继承自另一个entity的entities存在同一个SQLite的表里时,这个因素对设计SQLite的数据持久化时会存在性能上的问题。
定义属性和关系(Defining Attributes and Relationships)
Entity的特性有属性(Attributes)和关系(Relationships),如果有那么也包括取得属性(fetched properties -- 用于获得或者检索时的属性)。在其他特性中,每个属性都包含名称和类型。属性的名称不能跟NSObject或者NSManagedObject中的任何方法名相同,例如你不能把一个属性的名称定义成“description”。详情可以参考官方文档中的NSPropertyDescription.
临时属性是你定义定义为模型(model)的一部分属性,但不作为Entity的实例数据保存到数据持久区。Core Data会监测你对临时属性的修改,因此它们被记录用于撤销操作。你可以以任何方式对临时属性操作,包括计算值和得到值(calculated values and derived values)。
注意
如果采用非模型化的消息撤销改变一个临时属性,Core Data并不调用set储存器(访问器)与旧的值----它只是更新快照信息。
属性(Attributes)
如要定义属性(Attributes),在Core Data的数据模型编辑器中选中它,并在Core Data的数据模型显示窗口中指定属性的类型。Core Data支持多种属性类型,如字符串NSString、日期NSDate、数字NSNumber等等。
你也可以指定一个属性是可选的,也就是说他不一定要有一个值。然而,一般情况下,应该避免这样做,尤其是对于数值的情况。通常情况下,可以把属性的默认值,强制定义为0来得到比较好的结果。这是因为SQL对于空(NULL)的比较行为不同于Objective-C中的空(nil)。数据库中的NULL跟0不一样,并且搜索0与空的列不匹配。此外,数据库中的NULL也不等同于字符串的空(空字符串)。
关系和获取属性(Relationships and Fetched Properties)
如果要定义关系,在Core Data模型编辑器中选择它,在Relationships的窗口中指定值。
Core Data支持一对多的关系,并且获取属性。获取属性(Fetched Properties)是一个弱(weak)的单项属性。
类型弹出菜单(Type pop-up menu)定义一对一还是一对多的类型关系。关系的定义只能一次一个方向。如果要创建多对多的关系,那么需要创建两个一对多的关系,然后设置为互逆。
目标弹出菜单(Destination pop-up menu)定义在代码中访问关系时返回的对象(object)或者多个对象(objects)。如果定义为一个关系,则返回单个对象(或者为空nil)。如果定义为多个关系,则返回一个集合(或者为空nil)
反向弹出菜单(Inverse pop-up menu)定义了关系的另一半。因为每个关系都是从一个方向定义的,这个弹出菜单将两个关系接在一起,从而创建一个完全的双向关系。