50

当我向核心数据模型添加新属性时,我想让我的应用程序能够进行自动轻量级迁移。

在 Apple 的指南中,这是我能找到的关于该主题的唯一信息:

自动轻量级迁移

要请求自动轻量级迁移,您可以在 addPersistentStoreWithType:configuration:URL:options:error: 中传递的选项字典中设置适当的标志。您需要将与 NSMigratePersistentStoresAutomaticallyOption 和 NSInferMappingModelAutomaticallyOption 键对应的值设置为 YES:

NSError *error;
NSURL *storeURL = <#The URL of a persistent store#>;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
 
if (![psc addPersistentStoreWithType:<#Store type#>
    configuration:<#Configuration or nil#> URL:storeURL
    options:options error:&error]) {
    // Handle the error.
}

MyNSPersistentStoreCoordinator是这样初始化的:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }
    
    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"FC.sqlite"]];
    
    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    
    
    return persistentStoreCoordinator;
}

我无法查看应在何处以及如何添加 Apple 代码以使自动轻量级迁移正常工作?

4

5 回答 5

93

这就是我所做的自动轻量级迁移(来源:http ://brainwashinc.wordpress.com/2010/01/18/iphone-coredata-automatic-light-migration/ )

1. 在应用委托中设置自动迁移的 Persistent Store 选项。

将您的 persistentStoreCoordinator 创建更改为此(替换 YOURDB):

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

  if (persistentStoreCoordinator != nil) {
    return persistentStoreCoordinator;
  }

  NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"YOURDB.sqlite"]];

  // handle db upgrade
  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
  [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
  [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

  NSError *error = nil;
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
  }

  return persistentStoreCoordinator;
}

2. 版本化您的数据模型并编辑新文件。

选择您的 xcdatamodel 文件设计 -> 数据模型 -> 添加模型版本(扩展您的 xcdatamodeld 项目)选择“2”(或更高版本)文件,设计 -> 数据模型 -> 设置当前版本(编辑此版本)

3. 在 app delegate 中指定 momd 资源。

将您的 managedObjectModel 实现更改为此(替换 YOURDB)

- (NSManagedObjectModel *)managedObjectModel {

  if (managedObjectModel != nil) {
    return managedObjectModel;
  }

  NSString *path = [[NSBundle mainBundle] pathForResource:@"YOURDB" ofType:@"momd"];
  NSURL *momURL = [NSURL fileURLWithPath:path];
  managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];

  return managedObjectModel;
}
于 2010-02-22T16:01:13.957 回答
7

起初,上述解决方案对我不起作用。返回的 managedObjectModel 为 0x0。我认为这是因为我重命名了不同模型文件的文件名。如果您按照上面的说明进行操作,那么一切正常。

但是,如果您确实更改了模型文件名,那么您可以手动选择“当前”模型文件:假设您的原始模型文件是 MYMODEL.xcdatamodel 在执行上面的添加模型步骤之后,它会变成一个目录 MY.xcdatamodeld 并且在它下面你有MYMODEL.xcdatamodel 和 MYMODEL 2.xcdatamodel 将新模型文件重命名为您想要的任何名称,例如,假设您删除了 MYMODEL2.xcdatamodel 的空间并编辑其内容。现在在上面的代码中

NSString *path = [mainBundle pathForResource:@"MYMODEL2" ofType:@"mom" inDirectory:@"MYMODEL.momd"];
于 2010-03-14T23:08:40.800 回答
1

我认为这增加了最后一个答案。

起初,我发现捆绑资源和 .sqlite 名称的使用确实令人困惑。捆绑资源名称是否会随着版本的变化而变化?.sqlite 名称会改变吗?我现在已经开始进行迁移,并且了解到捆绑模型名称是指 XCode 中包含所有模型的目录/文件夹的名称,而不是该目录中模型版本的名称。

当您将 modelResource 名称指定给:

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:modelResource withExtension:@"momd"];
NSManagedObjectModel *theManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

该 modelResource 名称是 Xcode 中模型的目录/文件夹。

当你这样做时:

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:storeFileName];
    NSError *error = nil;

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        // handle error
    }

storeFileName 是 Documents 文件夹/目录中的 .sqlite 文件的名称(这不在包中)。

此外,当您从一个模型版本迁移到另一个模型版本时,默认情况下,.sqlite 文件名保持不变。

于 2013-10-09T19:16:32.143 回答
0

Oscar,针对您的问题,我最初发现了同样的事情。我建议删除新的 .xcdatamodeld 文件并将其重新添加到您的项目中,然后重新构建。希望有帮助!

于 2010-12-13T02:27:51.497 回答
0

斯威夫特 3 解决方案

1. 在应用委托中设置自动迁移的 Persistent Store 选项。

将您的 persistentStoreCoordinator 创建更改为此(替换 SingleViewCoreData.sqlite):

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {


let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")

let options = [
  NSMigratePersistentStoresAutomaticallyOption : Int(true),
  NSInferMappingModelAutomaticallyOption : Int(true)
]

do {

  try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)

} catch {

  print(error)
}

return coordinator

}()

2. 版本化您的数据模型并编辑新文件。

选择您的 xcdatamodel 文件 Editor>Add Model Version - 为您的新模型添加名称

于 2016-11-16T09:41:53.113 回答