Загрузить предыдущую версию модели

Я загружаю модель NSManagedObjectModel с помощью конструктора initWithContentsOfURL: следующим образом:

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

Однако это только дает мне доступ к последней/текущей версии модели. Можно ли загружать предыдущие версии с тем же самым файлом momd? как?

Ответы

Ответ 1

На самом деле вы можете загрузить более старую версию с помощью

- (NSManagedObjectModel *)managedObjectModelForVersion:(NSString *)version
{
        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"AppModel.momd/AppModel %@",version] withExtension:@"mom"];
        NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
        return model;
 }

Просто замените AppModel на название своей модели.

Я использую это, чтобы избавиться от липкой ситуации миграции вручную с использованием iCloud. Искал высоко и низко и не мог найти его нигде.

Ответ 2

Если вы просто хотите загрузить версию модели, совместимую с определенным существующим хранилищем, попробуйте:

NSError *error = nil;
NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType 
                                                                                         URL:storeURL 
                                                                                       error:&error];
NSManagedObjectModel *oldManagedObjectModel = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]] 
                                                                          forStoreMetadata:storeMetadata];

Обратите внимание: если вы используете идентификаторы версии XCode для версий модели данных, постоянные идентификаторы текущей версии сохраняются через запись NSStoreModelVersionIdentifiersKey в словаре метаданных хранилища.

Что касается загрузки конкретной произвольной версии, файлы mom обычно находятся под папкой momd в вашем приложении, поэтому вы можете перечислить их с помощью NSFileManager. Я считаю, что найти один с определенным идентификатором версии, вам придется использовать NSManagedObjectModel initWithContentsOfURL: initializer, а затем проверить свойство versionIdentifiers или использовать метод isConfiguration: compatibleWithStoreMetadata: instance для определения совместимости.

Ответ 3

Сделано решение, предлагаемое @Schoob, в категорию, потому что они рок.

@interface NSManagedObjectModel (version)
+ (NSManagedObjectModel *)modelFromBundle:(NSBundle *)bundle name:(NSString *)modelName version:(NSString *)version;
@end

@implementation NSManagedObjectModel (version)
+ (NSManagedObjectModel *)modelFromBundle:(NSBundle *)bundle name:(NSString *)modelName version:(NSString *)version
{
    if(!bundle)
        bundle = [NSBundle mainBundle];

    NSString *resource = [[modelName stringByAppendingPathExtension:@"momd"] stringByAppendingPathComponent:version];
    NSURL *modelURL = [bundle URLForResource:resource withExtension:@"mom"];
    NSAssert(modelURL,@"Unable to find MOM - %@",resource);
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    NSAssert(model,@"Unable to load MOM at URL- %@",modelURL);
    return model;
}
@end

Ответ 4

Быстрая версия. Замените имя файла.

import CoreData

extension NSManagedObjectModel
{
    class func model(forVersion version: Int) -> NSManagedObjectModel?
    {
        if let fileUrl = Bundle.main.url(forResource: "Model.momd/Model \(version)", withExtension: "mom")
        {
            return NSManagedObjectModel(contentsOf: fileUrl)
        }
        return .none
    }
}

Ответ 5

Нет, не предвидится, что это возможно. Я выхожу из NSManagedObjectModel documentation, где говорится о обсуждении свойства versionIdentifiers:

Это значение предназначено для использования в качестве подсказки для отладки, чтобы помочь вам определить модели, которые были объединены для создания объединенной модели.

Таким образом, похоже, вы не должны использовать предыдущие версии модели для вашей логики программы.