特定版本轻量级迁移后自定义代码执行

发布于 2024-11-17 22:15:07 字数 153 浏览 6 评论 0原文

我在 Core Data 中有 2 个对象模型(比如 v1 和 v2)。此迁移符合轻量级迁移的条件。现在,我想在迁移后执行自定义代码,但仅限于从 v1 迁移到 v2 时。稍后如果我引入 v3,我不希望执行自定义代码。

有办法做到这一点吗?

提前致谢, 阿努帕姆

I have 2 object models in Core Data (say v1 and v2). This migration is eligible for light weight migration. Now, I want to execute custom code after the migration but only when the migration is from v1 to v2. Later on if I introduce v3, I don't want the custom code to get executed.

Is there a way to do this?

Thanks in advance,
Anupam

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

野心澎湃 2024-11-24 22:15:07

以下是处理这种情况的方法,基本上是通过使用商店的元数据,正如 Apple 工程师在 WWDC 2010 上所建议的那样:

  • 打开商店(使用迁移选项)
  • 检查自定义密钥的元数据,例如“DonePostProcessing”
  • 进行后处理...
    • 填充派生属性
    • 插入或删除对象
    • 设置商店元数据(“DonePostProcessing”= YES)
  • 保存更改和元数据

或多或少,类似于



- (void)loadStoreWithMigration:(NSURL *)url {
    ...

   store = [psc addPersistentStoreWithType: NSSQLiteStoreType configuration: nil URL: url options: opts error: &err];

   m = [store metadata];
   key = @”DonePostProcessing”;
   if (m && ([[m objectForKey: key] integerValue] < 2) ){
      [self doPostProcessingInContext: context];
      m2 = [[m mutableCopy] autorelease];
      [m2 setObject: [NSNumber numberWithInteger: 2] forKey: key];
      [store setMetadata: m2];

      ok = [context save:&err];
   }

}

Here is how to handle this situation, basically by using the store's metadata, as suggested by Apple engineers at WWDC 2010:

  • Open the store (with migration options)
  • Check metadata for custom key, e.g. “DonePostProcessing”
  • Do post-processing...
    • Populate derived attributes
    • Insert or delete objects
    • Set store metadata (“DonePostProcessing” = YES)
  • Save changes and metadata

More or less, something like



- (void)loadStoreWithMigration:(NSURL *)url {
    ...

   store = [psc addPersistentStoreWithType: NSSQLiteStoreType configuration: nil URL: url options: opts error: &err];

   m = [store metadata];
   key = @”DonePostProcessing”;
   if (m && ([[m objectForKey: key] integerValue] < 2) ){
      [self doPostProcessingInContext: context];
      m2 = [[m mutableCopy] autorelease];
      [m2 setObject: [NSNumber numberWithInteger: 2] forKey: key];
      [store setMetadata: m2];

      ok = [context save:&err];
   }

}
岁月无声 2024-11-24 22:15:07

可能有更好的方法,购买这个应该可行:

通过在核心数据中保留一个名为“Information”的实体并拥有一个名为“CoreDataVersion”的属性来跟踪数据库版本。

迁移代码完成后,添加代码以检查核心数据中的版本号。

如果“CoreDataVersion”的值为“v1”并且您的应用程序现在处于“v2”(这可以对每个版本进行硬编码),请执行其他自定义代码,然后将新版本写回数据库。

如果您已经向用户发布了“v1”,只需说如果数据库中没有“CoreDataVersion”,那么它就是“v1”。

There might be a better way, buy this should work:

Keep track of the DB version by keeping an entity in Core Data named "Information" and have a property named "CoreDataVersion".

After the migration code finishes add code to check for the version number in the core data.

If the value of "CoreDataVersion" is "v1" and your app is now at "v2" (this can be hardcoded with each version), execute the additional custom code and then write the new version back to the DB.

If you already have "v1" published to users, just say that if there is no "CoreDataVersion" in the DB, then it is "v1".

清风挽心 2024-11-24 22:15:07
- (void) _performMaintanaceUpdate:(NSUInteger) newVersion oldVersion:(NSUInteger) oldVersion {
            if (newVersion>=1020500 && oldVersion < 1020500) {
                NSString *storePath = [[PreferenceDataModel getDataPath] stringByAppendingPathComponent: @"wcal.sqlite"];
                NSFileManager *fileManager = [NSFileManager defaultManager];
                if ([fileManager fileExistsAtPath:storePath]) {
                        [fileManager removeItemAtPath:storePath error:NULL];
                }
                [PreferenceDataModel setVersionOfLastMaintanace:newVersion]; 
            }
}

 (void) _checkAndPerformMaintenance{
    NSString* strVersion = [PreferenceDataModel getApplicationVersion];
    //legal version is xx.xx.xx where x is a dec digit 1.2 or 1.2.33 is legit 
    NSUInteger ver = 0;
    NSUInteger finalVer = 0;
    int t = 3; 

    for (int i=0; i<[strVersion length]; i++) {
        char c = [strVersion characterAtIndex:i];
        if (isdigit(c)) {
            ver*=10;
            ver+=c - 48;
        }
        else {
            finalVer+= ver * pow(100, t--); 
            ver = 0;
        }
    }
    finalVer+= ver * pow(100, t);
    [self _performMaintanaceUpdate:finalVer oldVersion:[PreferenceDataModel getVersionOfLastMaintanace]];
}

这就是您检索应用程序版本的方式

+(NSString *) getApplicationVersion {
    return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
}
- (void) _performMaintanaceUpdate:(NSUInteger) newVersion oldVersion:(NSUInteger) oldVersion {
            if (newVersion>=1020500 && oldVersion < 1020500) {
                NSString *storePath = [[PreferenceDataModel getDataPath] stringByAppendingPathComponent: @"wcal.sqlite"];
                NSFileManager *fileManager = [NSFileManager defaultManager];
                if ([fileManager fileExistsAtPath:storePath]) {
                        [fileManager removeItemAtPath:storePath error:NULL];
                }
                [PreferenceDataModel setVersionOfLastMaintanace:newVersion]; 
            }
}

 (void) _checkAndPerformMaintenance{
    NSString* strVersion = [PreferenceDataModel getApplicationVersion];
    //legal version is xx.xx.xx where x is a dec digit 1.2 or 1.2.33 is legit 
    NSUInteger ver = 0;
    NSUInteger finalVer = 0;
    int t = 3; 

    for (int i=0; i<[strVersion length]; i++) {
        char c = [strVersion characterAtIndex:i];
        if (isdigit(c)) {
            ver*=10;
            ver+=c - 48;
        }
        else {
            finalVer+= ver * pow(100, t--); 
            ver = 0;
        }
    }
    finalVer+= ver * pow(100, t);
    [self _performMaintanaceUpdate:finalVer oldVersion:[PreferenceDataModel getVersionOfLastMaintanace]];
}

and this is how you retrieve apps version

+(NSString *) getApplicationVersion {
    return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
}
永不分离 2024-11-24 22:15:07

在创建执行自动迁移的持久存储之前,请确定是否要迁移到版本 2。如果要迁移,请设置一个标志以在迁移发生后进行更改。

要确定要从中迁移的内容,请执行以下操作:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
NSString *version = [managedObjectModel.versionIdentifiers anyObject];

版本标识符在 Xcode 中设置。

Before you create the persistent store that does the automatic migration, determine if you'll be migrating to version 2. If you will be, set a flag to do your changes after the migration happens.

To determine what you'll be migrating from, do this:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
NSString *version = [managedObjectModel.versionIdentifiers anyObject];

The version identifiers are set in Xcode.

水溶 2024-11-24 22:15:07

另一种方法是进行从 v1 到 v2 的自定义数据迁移。首先查看 http://www.timisted.net/blog/archive/核心数据迁移/

Another way to do it is to do a custom data migration from v1 to v2. Start by looking over http://www.timisted.net/blog/archive/core-data-migration/.

稀香 2024-11-24 22:15:07

另一个对我来说效果很好的解决方案:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSInteger currVersion = [defaults integerForKey:@"dataModelVersion"];
    NSString *version = [managedObjectModel.versionIdentifiers anyObject];
    if (currVersion == 0) {
        [defaults setInteger:[version integerValue] forKey:@"dataModelVersion"];
    }
    else if (currVersion < [version integerValue]) {
        NSLog(@"Migration Code");
        [defaults setInteger:[version integerValue] forKey:@"dataModelVersion"];
    }

Another solution that worked well for me:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSInteger currVersion = [defaults integerForKey:@"dataModelVersion"];
    NSString *version = [managedObjectModel.versionIdentifiers anyObject];
    if (currVersion == 0) {
        [defaults setInteger:[version integerValue] forKey:@"dataModelVersion"];
    }
    else if (currVersion < [version integerValue]) {
        NSLog(@"Migration Code");
        [defaults setInteger:[version integerValue] forKey:@"dataModelVersion"];
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文