我有一个sqlite数据库,我在其中存储用户定义的信息和对用户只读的信息。我觉得将来可能需要修改只读信息,我不想进行整个数据迁移。有没有办法可以使用一个单独的sqlite数据库,可以很容易地替换为只读信息?如果是这样,你能否就如何做到这一点给出一点指示?我很困惑,因为我目前在xcdatamodel上有所有实体 - 我会创建两个数据模型吗?不确定这是怎么回事。提前谢谢。
这不起作用,但请随时提供反馈。
- (NSManagedObjectModel *)managedObjectModel {
NSLog(@"%s", __FUNCTION__);
if (managedObjectModel != nil) {
return managedObjectModel;
}
//managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
NSString *mainPath = [[NSBundle mainBundle] pathForResource:@"MyApp" ofType:@"mom"];
NSURL *mainMomURL = [NSURL fileURLWithPath:mainPath];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:mainMomURL];
[managedObjectModel setEntities:[NSArray arrayWithObjects:
[[managedObjectModel entitiesByName] objectForKey:@"Version"],
[[managedObjectModel entitiesByName] objectForKey:@"Book"],
nil] forConfiguration:@"info"];
[managedObjectModel setEntities:[NSArray arrayWithObjects:
[[managedObjectModel entitiesByName] objectForKey:@"Settings"],
[[managedObjectModel entitiesByName] objectForKey:@"Persons"],
nil] forConfiguration:@"main"];
return managedObjectModel;
}
和
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
NSLog(@"%s", __FUNCTION__);
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Main.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"Default" ofType:@"sqlite"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSString *infoStorePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Info.sqlite"];
if (![fileManager fileExistsAtPath:infoStorePath]) {
NSString *defaultInfoStorePath = [[NSBundle mainBundle] pathForResource:@"DefaultInfo" ofType:@"sqlite"];
if (defaultInfoStorePath) {
[fileManager copyItemAtPath:defaultInfoStorePath toPath:infoStorePath error:NULL];
}
}
NSURL *infoStoreUrl = [NSURL fileURLWithPath:infoStorePath];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
//persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] init];
NSPersistentStore *mainStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"main" URL:storeUrl options:options error:&error];
NSPersistentStore *infoStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"verses" URL:infoStoreUrl options:options error:&error];
NSManagedObject *settingsEntity = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Settings"] insertIntoManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext assignObject:settingsEntity toPersistentStore:mainStore];
NSManagedObject *persons = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Persons"] insertIntoManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext persons toPersistentStore:mainStore];
NSManagedObject *version = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Version"] insertIntoManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext assignObject:version toPersistentStore:infoStore];
NSManagedObject *book = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Book"] insertIntoManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext assignObject:book toPersistentStore:infoStore];
和
- (NSManagedObjectContext *)managedObjectContext {
NSLog(@"%s", __FUNCTION__);
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [NSManagedObjectContext new];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
答案 0 :(得分:3)
文档的部分答案:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/CoreData/Articles/cdMOM.html
配置
配置有一个名称和一个 相关的实体集。集合 可能重叠 - 即给定的实体 可能出现在多个 组态。你建立 以编程方式使用配置 setEntities:forConfiguration:或using Xcode数据建模工具(见 用于核心数据的Xcode工具)和 检索给定的实体 配置名称使用 entitiesForConfiguration:
您通常使用配置 你想存储不同的实体 在不同的商店。一个持久的 商店协调员只能有一个 托管对象模型,默认情况下 与给定相关的每个商店 协调员必须包含相同的内容 实体。解决这个问题 限制,你可以创建一个模型 包含所有的联合 您要使用的实体。然后是你 在模型中创建配置 每个实体的子集 你想用。然后你可以使用它 创建协调器时的模型。 添加商店时,请指定 不同的商店属性 组态。在创作时 但是,请记住你的配置 你无法创建跨店 关系。
然后,NSPersistentStoreCoordinator允许您创建多个存储,每个存储具有不同的配置。
任何人都有一个如何做到这一切的例子吗?
答案 1 :(得分:3)
您实际上可以使用单个数据模型来完成此任务,但是您需要手动(在代码中)将实体分配给不同的NSPersistentStore实例,只需要一些代码:
NSPersistentStoreCoordinator *coord = [[NSPersistentStoreCoordinator alloc] init];
NSPersistentStore *userStore = [coord addPersistentStoreWithType:NSSQLiteStore configuration:nil URL:someFileURL options:someoptions error:&error];
NSPersistentStore *otherStore = [coord addPersistentStoreWithType:NSSQLiteStore configuration:nil URL:someFileURL2 options:someoptions error:&error];
//Now you use the two separate stores through a managed object context that references the coordinator
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:coord];
NSManagedObject *userObject = [[NSManagedObject alloc] initWithEntity:entityDescFromModel insertIntoManagedObjectContext:context];
[context assignObject:userObject toPersistentStore:userStore];
NSManagedObject *otherObject = [[NSManagedObject alloc] initWithEntity:entityDescFromModel insertIntoManagedObjectContext:context];
[context assignObject:otherObject toPersistentStore:otherStore];
通过这种方式,您始终可以指定保留对象的商店。一旦对象位于各自的商店中,我认为您不必再执行任何额外的工作,即您应该只能执行在引用两个商店的协调器的上下文中获取规范。
答案 2 :(得分:2)
嗯,这就是我最终做的事情。两个managedObjectModels,两个managedObjectContexts,两个persistentStoreCoordinators,因此有两个持久存储。完全分开,这很好,因为两个商店中的数据根本没有关系。以下是为什么sqlite文件在没有实体且根本没有数据的情况下创建的原因:在创建实体之前,您需要在db中执行至少一个获取请求。谁知道?好吧,显然,不是我。无论如何,这对我来说效果很好,因为在应用程序启动之前我甚至都没有准备好第二个商店(这是一个额外的功能)。现在,当我的数据文件最终准备就绪时,我可以添加sqlite文件,取消注释与其相关的代码,并将应用程序发送到应用商店。它不会触及商店中的用户数据。而且,我将把我的只读存储保存在我的包中,所以不需要迁移。那声音怎么样?
答案 3 :(得分:0)
好的,我发现了如何添加其他数据模型。文件>新文件> Iphone OS>资源>数据模型。将我的实体移动到该数据模型。编译并似乎运行,但没有数据。问题是,仍然只有一个sqlite文件。需要了解如何使用两个,并将每个与适当的模型相关联。然后,应该能够在应用更新时覆盖新模型的默认sqlite文件。但我认为,我仍然需要进行迁移,因为它会在我指定的默认文件中在iPhone上创建一个sqlite文件。它不应该是一个艰难的迁移,我希望,因为我不会在文件中有任何用户数据。学习,但仍然有任何进一步的帮助。