【发布时间】:2012-04-15 17:45:33
【问题描述】:
在我们正在开发的应用程序中,我们使用 Core Data 和 sqlite 后备存储来存储我们的数据。我们应用程序的对象模型很复杂。此外,我们的应用程序提供的数据总量太大,无法放入 iOS(iPhone/iPad/iPod Touch)应用程序包中。由于我们的用户通常只对数据的一个子集感兴趣,因此我们以这样一种方式对数据进行了分区,即应用程序在应用程序包。在通过 iTunes 应用内购买支付额外内容后,我们的用户可以选择从我们的服务器下载额外的数据对象(大小约为 5 MB 到 100 MB)。 增量数据文件(存在于 sqlite 后备存储中)使用与捆绑包附带的数据相同的 xcdatamodel 版本;对象模型的变化为零。增量数据文件作为 gzip 压缩的 sqlite 文件从我们的服务器下载。我们不希望通过随应用程序提供增量内容来膨胀我们的应用程序包。此外,我们不想依赖对 web 服务的查询(因为复杂的数据模型)。 我们已经测试了从我们的服务器下载增量 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)显示为 附加到末尾的 incrementalStoreURL 中的数据 来自 defaultStoreURL 的数据。
- 有些对象是重复的。有很多实体 我们数据模型中的只读数据;当我们添加时,这些会重复 第二个persistentStore 到persistentStoreCoordinator。
理想情况下,我们希望 Core Data 将来自两个持久存储的对象图合并为一个(在数据下载时来自两个存储的数据之间没有共享关系)。此外,我们想删除重复的对象。 在网上搜索时,我们看到有人提出了一些问题,他们试图做与我们正在做的事情相同的事情——例如this answer 和this answer。我们已经阅读了Marcus Zarra's blog on importing large data sets in 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 所建议的解决方案。数据的大小可能会阻止我们手动读取增量数据并将其重新插入到默认存储中。我的问题是:从两个持久存储(具有相同的 objectModel)中获取对象图以合并到一个持久存储中的最有效方法是什么?
当我们向对象图添加新的实体属性或修改关系时,自动迁移非常有效。是否有一种简单的解决方案可以将相似的数据合并到同一个持久存储中,该存储具有足够的弹性以停止和恢复——因为完成了自动迁移?
【问题讨论】:
-
当我需要 Marcus Zarra 时他在哪里?我使用 [NSPersistentStore migratePersistentStore:toURL:options:withType:error] 方法取得了一些进展。我只需要更多的清理代码就可以到达我需要的地方。
-
我也在为同样的事情苦苦挣扎。你能发布你到目前为止的想法吗?我迷路了。
-
完成!让我知道结果如何。
-
@Sunny 我也面临一些类似的问题,你能帮我看看吗stackoverflow.com/questions/33694048/…
-
@anoop4real,我发布了你的问题的答案,看看。接受答案,如果我误解了问题,请告诉我。
标签: objective-c core-data merge core-data-migration object-graph