问题陈述
当尝试将记录保存到作为分配给同一 PersistentStoreCoordinator 的两个 SQLite 存储之一的读/写存储时,我的 iPhone 应用程序崩溃。保存记录时一个明显的问题是 PersistentStoreCoordinator 不知道将数据保存在哪个 Store 中(只是因为我不知道如何实现这一点)。
首先,我将提供总体情况以确保我的方法是合理的。然后我将提供实现细节。
背景
这是一个简化的示例,代表了我正在开发的实际应用程序的关键方面。
种子数据
用户输入场景
当前实施
核心数据实现
数据存储和检索
当然,在查看选择列表以对属性进行选择时,不应向用户提供任何证据表明选择来自两个不同的商店。
持久存储协调器设置
- (NSPersistentStoreCoordinator*)persistentStoreCoordinator {
if (_persistentStoreCoordinator == nil) {
NSArray *bundles = @[[NSBundle bundleForClass:[self class]]];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:bundles]];
NSError *error;
//--------------------------------------------------
// Set options for the USER DATA Persistent Store.
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
//--------------------------------------------------
// Add the USER DATA Store to the Persistent Store Coordinator.
NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.persistentStorePathForUserData
options:options
error:&error];
//--------------------------------------------------
// Set options for the SEED DATA Persistent Store.
options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSReadOnlyPersistentStoreOption : @YES};
//--------------------------------------------------
// Add the SEED DATA Store to the Persistent Store Coordinator.
persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.persistentStorePathForSeedData
options:options
error:&error];
}
return _persistentStoreCoordinator;
}
重要目标
请记住以下几点:
- 如果可能的话,我更愿意进行种子数据更新,而不必在幕后管理数据版本(即仅提供应用程序更新,只提供新的或更改的种子数据记录并以某种方式处理删除)或实现版本检查功能处理用户从版本 n 升级到 n+5 的情况的代码。
- 用户数据和种子数据不应包含两者之间的任何重复记录并使用相同的 ManagedObjectModel。所以从数据和模型的角度来看,应该没有必要合并两个商店或将一个商店迁移到另一个商店。
研究
在这种情况下, 将对象从多个存储保存到单个持久存储,这两个存储被合并,然后获取所有记录,剔除重复项并保存上下文。我希望不必合并然后检查数以千计的重复记录。(参见上面的重要目标#2。)
在这种情况下, 合并两个 iOS 核心数据持久存储的有效方法是什么?,某些实体是只读的,而其他实体是读/写的。在我的应用程序中,种子数据存储中的所有实体都是只读的,用户数据存储中的相同实体是读/写的。所以我认为迁移不适用。(参见上面的重要目标#2。)
在 Apple 的“Persistent Store Coordinator”下的Core Data Programming Guide中,图 4“高级持久性堆栈”显示了使用两个 Store 的 Core Data 实现,但同样,每个 Store 都配置有单独且不同的对象。在我的应用程序中,每个对象都出现在每个商店中。
此处提出的解决方案 Combining Two SQLite Stores Into One,相对于在不同存储中的对象之间没有关系的两个存储似乎是相关的,但没有提供与我实现的内容进行比较的细节。
我已经阅读了Marcus Zarra 撰写的 Core Data (2nd Edition) 的前三章,但他没有使用两个不需要迁移的商店。然而,第 3 章确实提供了一个非常清晰的版本控制示例。(它的复杂性使我达到了上面的重要目标#1。)
这个解决方案,默认情况下在 iPhone 的核心数据中使用哪个持久存储,建议使用 ManagedObjectModel 的多个配置,但每个实体都分配给一个且只有一个配置。我不确定这个解决方案如何,甚至是否可以推断到我的情况。
也许这里提出的解决方案是NSPersistentStoreCoordinator 具有两种类型的持久存储?,接近我需要的。不幸的是,只处理请求。我在 NSManagedObjectContext 类中没有看到类似于 NSFetchRequest 方法的方法 setAffectedStores 用于保存。