Core data 加载以前的模型版本

Core data 加载以前的模型版本,core-data,object-model,Core Data,Object Model,我正在加载带有initWithContentsOfURL:构造函数的NSManagedObjectModel模型,如下所示: NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyDocument" withExtension:@"momd"]; NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 但

我正在加载带有initWithContentsOfURL:构造函数的NSManagedObjectModel模型,如下所示:

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

但是,这只允许我访问模型的最新/当前版本。是否可以使用相同的momd文件加载以前的版本?怎么做?

不,这是不可能的。我从
NSManagedObjectModel
中推断,其中提到讨论属性
versionIdentifiers

此值将用作调试提示,以帮助您确定组合以创建合并模型的模型


因此,您似乎不应该在程序逻辑中使用以前的模型版本。

如果您只想加载与特定现有存储兼容的模型版本,请尝试:

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方法来确定兼容性

实际上,您可以使用以下内容加载旧版本:

- (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的棘手的手动迁移情况。到处搜索,都找不到这个。

将@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

快速版本。替换文件名

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

您通常如何进行自定义迁移?为了暂时解决这个问题,我为我的数据模型制作了一个文件夹副本(其中再次包含所有版本),并将我想要支持的旧版本设置为默认版本。这样我就可以构建NSMigrationManager所需的NSManagedObjectModel的新旧实例我不同意这一点。请查看我的版本(7.1)上的my answer.fyi版本。mom位于与版本同名的文件中(因此@“../%@”,版本而不是@“/…/AppModel%@”,版本),并检查是否存在nil storeMetadata,在这种情况下,您没有现有数据库,因此需要创建一个!