持久化存储协调器会试着用新版的模板打开原来的持久化存储区,但是那是旧的模板,旧的格式,当然会出错。现在要做的就是迁移现有的持久化数据区,以便跟新模型匹配。
怎么进行迁移呢?
在什么时候进行迁移?
在向NSPersistentStoreCoordinator添加存储区的时候。
那么如何添加呢?
答案是,将下列选项放到NSDictionary里传过去,就会自动完成存储区的迁移工作。
- 如果传给NSPersistentStoreCoordinator的NSMigratePersistentStoresAutomaticallyOption是YES,那么Core Data就会试着把低版本持久化存储区迁移到最新版本的模型
- 如果传给NSPersistentStoreCoordinator的NSInferMappingModelAutomaticallyOption是YES,那么Core Data 会试着以最合理的方式自动推断出 “源模型实体” 中某个属性对应 “目标模型实体” 中的哪一个属性
- 假如在开发Core Data程序的时候海使用了iCloud,那么只能采用这种迁移方式
- 把上面的两个选项打开后,就是 轻量级迁移(lightweight migration)
修改CoreDataHelperd的 loadStore方法如下:
NSDictionary *options = @{ NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES, NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"} }; NSError *error = nil; _store = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self storeURL] options:options error:&error];
下面我要为新的实体创建50000条数据。
不知道作者为什么要搞这么多条,用了大概2分钟才执行完,由于作者每次都修改demo ,会删除原来的数据,难道就不能用demo1,demo2吗?
- (void)demo2 { if (debug == 1) { NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd)); } for (int i=0; i<50000; i++) { Measurement *newMeasurement = [NSEntityDescription insertNewObjectForEntityForName:@"Measurement" inManagedObjectContext:_coreDataHelper.context]; newMeasurement.abc = [NSString stringWithFormat:@"-->> LOTS OF TEST DATA x%i",i]; NSLog(@"Insert %@",newMeasurement.abc); } [_coreDataHelper saveContext]; }
然后打印出来
- (void)demo3 { if (debug == 1) { NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd)); } NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Measurement"]; [request setFetchLimit:50]; NSError *error = nil; NSArray *fetchedobjects = [_coreDataHelper.context executeFetchRequest:request error:&error]; if (error) { NSLog(@"%@",error); }else{ for (Measurement *measurement in fetchedobjects) { NSLog(@"Fetched Object = %@", measurement.abc); } } }
注:migrate 是 “迁移”,Infer 是 “推断”,pragmas 是 “语法”。