我们正在开发的应用程序中,使用了带有sqlite后备存储的Core Data来存储数据。我们的应用程序对象模型很复杂。此外,我们应用程序提供的数据量太大,无法适合于iOS(iPhone/iPad/iPod Touch)应用程序包。由于我们的用户通常只对数据的子集感兴趣,因此我们将我们的数据划分为这样一个方式:应用程序与子集一起发布(尽管是大约100 MB的子集)。通过iTunes应用内购买付款后,我们的用户可以选择下载其他数据对象(大小为5 MB到100 MB)。 增量数据文件(存在于sqlite后备存储中)使用与捆绑包中数据相同的xcdatamodel版本;对象模型没有任何更改。增量数据文件作为gzipped sqlite文件从我们的服务器下载。我们不想通过在应用程序中包含增量内容来膨胀我们的应用程序包。另外,我们也不想依赖于WebService查询(因为数据模型很复杂)。 我们已经测试了从服务器下载增量sqlite数据的过程。我们已经能够将下载的数据存储添加到应用程序的共享persistentStoreCoordinator中。
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:defaultStoreURL options:options error:&error])
{
NSLog(@"Failed with error: %@", [error localizedDescription]);
abort();
}
// Check for the existence of incrementalStore
// Add incrementalStore
if (incrementalStoreExists) {
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error])
{
NSLog(@"Add of incrementalStore failed with error: %@", [error localizedDescription]);
abort();
}
}
}
然而,这种方法有两个问题:
- 使用数据获取结果(例如NSFetchResultController)时,增量存储URL中的数据将附加到默认存储URL的数据末尾。
- 一些对象会被复制。在我们的数据模型中有许多只读数据实体;当我们将第二个persistentStore添加到persistentStoreCoordinator时,它们会被复制。
理想情况下,我们希望Core Data将来自两个persistent stores的对象图合并为一个(下载数据时两个store之间没有共享关系)。此外,我们还希望删除重复的对象。通过搜索网络,我们看到了一些人试图做与我们相同的事情的问题,例如这个答案和这个答案。我们已经阅读了Marcus Zarra在Core Data中导入大量数据集的博客。然而,我们看到的所有解决方案都无法解决我们的问题。我们不想手动读取和保存增量存储中的数据到默认存储,因为我们认为这样会非常慢,并且在手机上容易出现错误。有没有更有效的方法来进行合并?
我们已经尝试通过实现手动迁移来解决问题,如下所示。但是,我们还没有成功地使合并发生。我们对上面引用的答案1和2提出的解决方案并不太清楚。Marcus Zarra的博客解决了我们项目最初导入大型数据集到iOS时遇到的一些问题。
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:__managedObjectModel destinationModel:__managedObjectModel];
if (![migrator migrateStoreFromURL:stateStoreURL
type:NSSQLiteStoreType
options:options
withMappingModel:nil
toDestinationURL:destinationStoreURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&error])
{
NSLog(@"%@", [error userInfo]);
abort();
}
}
看起来,答案1的作者最终从增量存储中读取了他的数据,并保存到默认存储中。也许我们误解了文章1和2所提出的解决方案。由于我们的数据量可能使我们无法手动读取和重新插入增量数据到默认存储中,我的问题是:什么是将具有相同对象模型的两个persistentStores中的对象图合并成一个persistentStore的最有效方式?
当我们向对象图添加新实体属性或修改关系时,自动迁移效果相当不错。是否有一种简单的解决方案可以将类似的数据合并到同一持久存储中,并且足够强大以停止和恢复 - 就像自动迁移一样?