《Core Data应用开发实践指南》一3.4 默认的迁移方式

3.4 默认的迁移方式

有时候我们需要比轻量级迁移更为精细的控制手段。比方说,我们要把Measurement实体替换成另外一个名叫Amount的实体,并且还想把Measurement实体中名叫abc的那个属性迁移到Amount实体中的xyz 属性上面。abc中已有的数据也要迁移到xyz属性。为了完成这些需求,开发者需要创建模型映射,以便手工指明映射关系。在添加持久化存储区时,即便NSInferMappingModelAutomaticallyOption选项设为YES,Core Data也还是会先检测有没有文件,如果有的话,那么在执行自动推断之前,它会先试着使用这个文件来迁移。在测试映射模型之前,建议先禁用该选项,这样才可以确定映射模型是不是已经付诸使用并且能够正常运作了。
请按下列步骤修改Grocery Dude,以禁用自动化模型映射功能:
修改CoreDataHelper.m文件中的loadStore方法,把NSInferMappingModelAutomaticallyOption设为@NO。
请按下列步骤修改Grocery Dude,以便添加新模型,为从Measurement实体迁移到Amount实体做准备:
1. 可以先抓取一份快照或备份整个项目。
2. 根据Model 2版本来创建新版模型,将其命名为Model 3。
3. 选中Model 3.xcdatamodel。
4. 删除Measurement实体。
5. 新建Amount实体,并向其中添加类型为String的xyz属性。
6. 根据Amount实体创建NSManagedObject子类。在保存类文件这个步骤中,别忘了勾选targets中的“Grocery Dude”。
7. 将Model 3设为当前模型版本。
8. 运行应用程序,目前它应该出错并崩溃。错误信息如图3-5所示。

为了解决图3-5中的错误,我们需要创建映射模型,以指明字段之间的映射关系。具体到本例来说,就是要把旧模型中Measurement实体的abc属性迁移为新模型中Amount实体的xyz 属性。
请按下列步骤修改Grocery Dude,以添加新的映射模型:
1. 确保Data Model 组处于选中状态。
2. 点击File>New>File...菜单项。
3. 选择iOS>Core Data>Mapping Model,并点击Next按钮。
4. 把Model 2.xcdatamodel选为Source Data Model,并点击Next按钮。
5. 把Model 3.xcdatamodel选为Target Data Model,并点击Next按钮。
6. 将mapping model的名称设为Model2toModel3,并将其保存。
7. 确保Targets中的“Grocery Dude”处于勾选状态,然后点击Create按钮。
8. 选中Model2toModel3.xcmappingmodel。
现在你将看到如图3-6所示的model-mapping editor界面。

Xcode目前呈现的这套映射是Core Data以最合理的方式推断出来的。在界面左方,应该会看到ENTITY MAPPINGS字样,它下面列出了源实体与目标实体之间的映射。通过图3-6我们应该可以看到,Core Data已经推断出源Item实体对应于目标Item实体,而这个推断是合理的。实体映射时所采用的命名标准是SourceToDestination(源实体名到目标实体名)。明白了这一点之后,我们就会发现,Amount实体并没有与之对应的源实体,因为Amount没有出现在源模型里面。
请按下列步骤修改Grocery Dude,以便将旧版模型的Measurement实体映射到新版模型的Amount实体:
1. 确保Model2toModel3.xcmappingmodel处于选中状态。
2. 在ENTITY MAPPINGS中选定Amount。
3. 点击View>Utilities>Show Mapping Model Inspector菜单项(假如菜单里没有这一项,可以按“Option++3”组合键),然后应该就会看到如图3-7所示的面板了。
4. 在Entity Mapping区域中,把Amount实体的Source设置成Measurement。设置好的结果如图3-7所示。

由于我们把Measurement选为源实体,而把Amount选为目标实体,所以Mapping Name这一栏就自动变成了MeasurementToAmount。此外,映射的Type(类型)也从Add变成了Transform。如果要实现更为复杂的迁移方式,那么可以在Custom Policy文本框中输入类名,这个类应该是NSEntityMigrationPolicy的子类。在该子类中,可以通过覆写createDestinationInstancesForSourceInstance方法而操作待迁移的数据。比方说,可以拦截abc这个属性的值,将其中每个单词的首字母改为大写,然后再把修改过的值迁移到xyz属性。
图3-7底部的Source Fetch选项可通过谓词(在Filter Predicate文本框中输入)限定迁移过来的数据量。假如只想把旧数据中的一部分迁移过来,那么这个选项就很有用了。此处的谓词格式与通常代码中编写的谓词相似,只不过要用$source变量来表示源数据。比方说,如果想把abc属性为nil的源数据排除掉,那么可将谓词写成$source.abc!=nil。
在前述的图3-6中,选定ENTITY MAPPINGS字样下方的ItemToItem实体,并观察属性映射中的内容,会看到目标实体中的每个属性都设置有对应的Value Expression。现在再来查看MeasurementToAmount实体的映射,会发现xyz这个Destination 属性并没有设置Value Expression。这就意味着xyz属性目前还没有对应的Source 属性,需要按照ItemToItem实体映射中的那种格式,给它设置一条Value Expression。我们一开始提出的需求是把abc属性映射到xyz属性,所以接下来就按照这个需求配置Value Expression。
请按下列步骤修改Grocery Dude,给名为xyz的Destination 属性设置适当的Value Expression:
1. 在MeasurementToAmount的实体映射界面中,把xyz这个Destination 属性的Value Expression设置为$source.abc。
迁移模型虽然已经配置好了,但demo方法仍然会从Measurement实体获取数据,而在新模型中,是没有这个实体的。
请按下列步骤修改Grocery Dude,令demo方法使用Amount实体而非Measurement实体:
1. 把AppDelegate.m文件顶部的#import "Measurement.h"替换为#import "Amount.h"。
2. 修改AppDelegate.m文件的demo方法,用程序清单3-4中的代码替换原有代码。原来的代码是获取一小部分Measurement样例数据,而这段代码也与之相似,它是获取一小部分Amount数据。
3. 运行应用程序。由于要迁移数据,所以加载屏幕的显示时间可能会稍微长一些,具体情况与电脑速度有关。

只要迁移过程顺利完成,程序就不会崩溃,你应该会在控制台的日志中看到如图3-8所示的信息。

为了验证迁移后的数据是否已经保存到持久化存储区,我们可以用第2章中讲过的办法来查看Grocery-Dude.sqlite文件的内容。正确的结果应该如图3-9所示,其中多出了名为ZAMOUNT的表(这张表对应于Amount实体),旧的Measurement实体里的数据现已出现在这张表中。

在学习下一节之前,一定要先关掉SQLite Database Browser。

时间: 2024-09-13 20:10:03

《Core Data应用开发实践指南》一3.4 默认的迁移方式的相关文章

《Core Data应用开发实践指南》一3.5 通过迁移管理器来迁移数据

3.5 通过迁移管理器来迁移数据 除了通过NSPersistentStoreCoordinator来迁移存储区之外,还可以采用迁移管理器来做.迁移管理器可以使开发者全权掌控迁移过程中创建的文件,从而令他们能够按自己的方式来灵活处理迁移中的各种问题.使用迁移管理器的一个好处就是可以向用户报告迁移进度,使用户知道应用程序哪次会启动得比较慢一些,所以需要耐心等待.虽说迁移过程理应执行得非常快才对,但当数据库比较大.变动比较复杂时,迁移过程就需要耗费一定的时间了.为了使用户界面保持流畅,迁移过程必须在后

《Core Data应用开发实践指南》一1.2 Core Data的适用场合

1.2 Core Data的适用场合 如果应用程序要保存的设置数据太多,以致NSUserDefaults及"特性列表"(property list)这种简单的存储方案无法应付,那么就会出现内存占用量方面的问题.解决办法是直接使用数据库或通过Core Data来间接操作数据库.选用Core Data的好处是,不用再花时间编写数据库接口的代码了.此外,你还将享受性能方面的优势,而且可以使用诸如撤销及验证等强大的功能.假如选择直接使用数据库,那就要花时间去做开发与测试工作,也就是通常所说的&

《Core Data应用开发实践指南》一3.1 修改托管对象模型

3.1 修改托管对象模型 在应用程序的进化过程中,其托管对象模型也可能需要改变.对于一些比较简单的修改,诸如设定属性的默认值.设定验证规则.使用获取请求模板等,是可以直接实施的.而对于另外一些更为结构化的(structural)修改,则需先把持久化存储区迁移到新的模型版本才行.假如没有提供迁移数据所需的映射与设定,那么应用程序就会崩溃.为了继续构建范例程序,需要把上一章中的代码添加到Grocery Dude项目中.或者可以去http://www.timroadley.com/LearningCo

《Core Data应用开发实践指南》一2.2 添加托管对象模型

2.2 添加托管对象模型 在第1章中,我们通过CoreDataHelper.m文件里的mergedModelFromBundles方法初始化了托管对象模型.然而现在的问题是:项目里根本就没有模型可用!如果连模型都没有的话,那Core Data就彻底失去意义了,所以,我们这个时候应该创建模型文件.模型文件一般会含有"对象图",而对象图则用来表示应用程序的数据结构以及其他一些可以简化应用程序开发的东西,我们稍后再来解释.请按下列步骤修改Grocery Dude,以便添加数据模型文件: 在现

《Core Data应用开发实践指南》一第1章 初次尝试Core Data应用程序

第1章 初次尝试Core Data应用程序 如果不能把一件事用简单的话说清楚,那就表明你理解得还不够透彻.-阿尔伯特•爱因斯坦"体验式学习"(kinesthetic learning)或者说"从实践中学习"(learning by doing),是接收并记住信息的绝佳手段.即便对于许多有经验的程序员来说,Core Data也是个相当棘手的话题,于是,笔者就适时地编写了你手中的这本书,它以实践的方式来讲解Core Data.本书不会过早地讲解一些比较难懂的话题,本章只

《Core Data应用开发实践指南》一1.3 创建Grocery Dude项目

1.3 创建Grocery Dude项目 Grocery Dude是个运行在iPhone上的范例程序,在学习本书的过程中,你将了解到它的制作流程.学会了Core Data中的某个特性或某项开发技巧之后,你可以将其运用在Grocery Dude程序上面.到了本书收尾的时候,你将会制作好一款功能完备而且运行速度很快的Code Data程序,它能够同iCloud紧密地集成在一起.假如你现在就想直接看看成品,那可以去App Store下载Grocery Dude.请注意,Grocery Dude是专门为

《Core Data应用开发实践指南》一3.3 轻量级的迁移方式

3.3 轻量级的迁移方式 把新模型设为当前版本之后,必须迁移现有的持久化存储区,只有这样,才能正常使用新模型.这是因为,持久化存储区协调器会试着用新版的模型来打开原有的存储区,但由于原有的存储区是用旧版模型创建的,所以该操作会失败.在向NSPersis-tentStoreCoordinator添加存储区的时候,只需将下列选项放在NSDictionary里传过去,即可自动完成存储区的迁移工作:如果传给NSPersistentStoreCoordinator的NSMigratePersistentS

《Core Data应用开发实践指南》一1.4 为现有的应用程序添加Core Data支持

1.4 为现有的应用程序添加Core Data支持 在Xcode中创建iOS应用程序项目时,可以使用各种起始模板(starting-point template).假如要根据Master-Detail.Utility Application或Empty Application等模板来创建项目,那么只需勾选Use Core Data,即可在项目中使用Core Data.不过,Grocery Dude项目是根据Single View Application模板创建的,它起初并没有包含Core Dat

《Core Data应用开发实践指南》一2.12 后端SQL的可见性

2.12 后端SQL的可见性 如果只在控制台的日志中查看Core Data所输出的结果,那么意义并不算太大.你知不知道这些事情背后究竟发生了什么?Core Data对持久化存储区中的数据到底进行了哪些操作?这些操作是否恰当?为了提供无缝的Core Data体验,系统都生成了哪些SQL查询语句?每次在模拟器中运行程序的时候,是不是会插入重复的对象? 有个极其详尽的调试选项可以提供足够的信息,告诉你这些操作背后所发生的事情,从而令你知道上述那些问题的答案.这个调试选项会把系统自动生成的SQL查询语句