轻量级数据迁移(下称LM), Core Data 自动执行,适用模型简单改变(simple changes),包括:实体/表中增加新属性/字段,LM 与普通迁移原理完全一样,只是不需要映射模型 (mapping model) (参见 “Mapping Overview” ),Core Data 自行推测(infers)版本间的差异。
LM 适用于APP早期开发,那时总是在改变数据结构,同时没有必要保存一些测试数据。另一个好处是,当你使用推测模型(inferred model)和 SQLite 存储时,Core Data 可以执行就地(in situ)迁移,严格讲,直接生成并执行 SQL 语句。因为没有载入任何数据,所以此时能保证效率。
LM中 Core Data 必须能推测出映射关系
Core Data 需要能够在运行时找到源和目标的映射关系,一般我们将数据模型存放在 bundles文件夹中(使用 NSBundle 的 allBundles 和 allFrameworks 方法获得)Core Data可以找到并发现它,如果放在别的地方,需要按照 “Use a Migration Manager if Models Cannot Be Found Automatically .” 中说的做。Core Data 随后自动分析现有表和字段的变化,自动产生推测的映射模型(inferred mapping model)。
以下几种情况,Core Data 可以自动推测出:
添加新属性/字段
删除属性/字段
必填属性/字段改为可选属性/字段
可选属性/字段改为必填属性/字段,并设置默认值
重命名实体/表或属性/字段
如果要重命名,需要将新版本中新实体/属性的“重命名标识符”(renaming identifier)的值设置为原来的实体名或属性名。具体方法:Xcode Data Modeling 工具->属性查看器(property inspector)。可以想象,这样做以后,如一个属性的名字在三次修改中都变化了,且都标记了重命名标识符,这样不管是从 version 2 到 version 3 还是从 version 1 到 version 3 都可以无错误的迁移。
另外,Core Data 还可以自动猜测出:
使用选项字典(Options Dictionary)请求自动迁移(Automatic Migration)
定义选项字典,将 NSMigratePersistentStoresAutomaticallyOption 和 NSInferMappingModelAutomaticallyOption 两个键值设置为YES,然后调用 addPersistentStoreWithType:configuration:URL:options:error:
02
NSURL *storeURL = <#The URL of a persistent store#>;
03
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
04
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
05
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
06
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
08
BOOL
success = [psc addPersistentStoreWithType:<#Store type#>
09
configuration:<#Configuration or nil#> URL:storeURL
10
options:options error:&error];
可以使用 NSMappingModel 的 inferredMappingModelForSourceModel:destinationModel:error: 方法,获取推测的映射模型,如果可以推测出返回,如果不可以,返回 nil。
如果不能自动找到模型,则使用迁移管理器(Migration Manager)
执行自动迁移,必须保证 Core Data 能够在运行时找到源对象模型和目标对象模型,如果你需要将模型存放于自动搜索范围之外,那么需要我们自己生成推测的模型,并实例化迁移管理器(NSMigrationManager)。如下面的代码,这些代码假设已经实现了sourceModel 和 destinationModel,这两个方法分别返回源对象和目标对象。
01
- (
BOOL
)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError {
04
NSMappingModel *mappingModel =
05
[NSMappingModel inferredMappingModelForSourceModel:[self sourceModel]
06
destinationModel:[self destinationModel] error:outError];
14
NSMigrationManager *manager = [[NSMigrationManager alloc]
15
initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]];
17
BOOL
success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType
18
options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL
19
destinationType:NSSQLiteStoreType destinationOptions:nil error:outError];