为核心数据(iPhone)实施“自动轻量级迁移”

时间:2010-02-22 10:23:28

标签: iphone core-data data-migration

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

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

  

自动轻量级迁移

     

要求自动轻量级   迁移,您设置适当的标志   在您传入的选项字典中   addPersistentStoreWithType:配置:网址:选项:错误:。   您需要设置相应的值   两个人   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.
}

我的NSPersistentStoreCoordinator以这种方式初始化:

- (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代码以使自动轻量级迁移工作?

5 个答案:

答案 0 :(得分:93)

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

1。在应用程序委托中为自动迁移设置持久存储选项。

将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文件 设计 - &gt;数据模型 - &gt;添加模型版本(展开您的xcdatamodeld项目) 选择“2”(或更高版本)文件,Design - &gt;数据模型 - &gt;设置当前版本(编辑此版本)

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;
}

答案 1 :(得分:7)

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

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

NSString *path = [mainBundle pathForResource:@"MYMODEL2" ofType:@"mom" inDirectory:@"MYMODEL.momd"];

答案 2 :(得分:1)

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

我发现bundle资源和.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文件名保持不变。

答案 3 :(得分:0)

奥斯卡,在回答你的问题时,我最初发现了同样的事情。我建议删除并重新添加新的.xcdatamodeld文件到您的项目,然后重建。希望有所帮助!

答案 4 :(得分:0)

Swift 3解决方案

<强> 1。在应用程序委托中设置自动迁移的持久存储选项。

将persistentStoreCoordinator创建更改为this(替换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文件编辑器&gt;添加模型版本 - 为新模型添加名称