Выполнение пользовательского кода после облегченной миграции конкретной версии - PullRequest
12 голосов
/ 30 июня 2011

У меня есть две объектные модели в Базовых данных (скажем, v1 и v2). Эта миграция имеет право на легкую миграцию. Теперь я хочу выполнить пользовательский код после миграции, но только когда миграция с v1 на v2. Позже, если я представлю v3, я не хочу, чтобы пользовательский код выполнялся.

Есть ли способ сделать это?

Спасибо заранее, Anupam

Ответы [ 6 ]

10 голосов
/ 15 ноября 2011

Вот как справиться с этой ситуацией, в основном, используя метаданные магазина, как предложили инженеры Apple на WWDC 2010:

  • Открыть магазин (с возможностью миграции)
  • Проверьте метаданные для пользовательского ключа, например, «DonePostProcessing»
  • Выполнить постобработку ...
    • Заполнить производные атрибуты
    • Вставка или удаление объектов
    • Установить метаданные магазина («DonePostProcessing» = ДА)
  • Сохранить изменения и метаданные

Более или менее, что-то вроде



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

}
1 голос
/ 10 ноября 2011

Другой способ сделать это - выполнить пользовательскую миграцию данных из v1 в v2. Начните с просмотра http://www.timisted.net/blog/archive/core-data-migration/.

1 голос
/ 10 ноября 2011

Прежде чем создавать постоянное хранилище, которое выполняет автоматическую миграцию, определите, будете ли вы переходить на версию 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.

1 голос
/ 09 ноября 2011
- (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"];
}
1 голос
/ 08 ноября 2011

Возможно, есть лучший способ, но это должно работать:

Отслеживайте версию БД, сохраняя сущность в Базовых данных с именем «Информация» и обладающую свойством с именем «CoreDataVersion».

После того, как код миграции завершится, добавьте код, чтобы проверить номер версии в основных данных.

Если значение «CoreDataVersion» равно «v1», а ваше приложение теперь находится на «v2» (это можетбыть жестко запрограммированными для каждой версии), выполнить дополнительный пользовательский код и затем записать новую версию обратно в БД.

Если у вас уже есть «v1», опубликованный для пользователей, просто скажите, что если нет «CoreDataVersion»в БД то это "v1".

0 голосов
/ 19 мая 2014

Еще одно решение, которое хорошо сработало для меня:

    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"];
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...