18

我正在使用 initWithContentsOfURL: 构造函数加载 NSManagedObjectModel 模型,如下所示:

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

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

4

5 回答 5

36

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

- (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 的棘手手动迁移情况。搜索了高低,在任何地方都找不到。

于 2012-09-12T14:59:46.097 回答
4

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

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: 初始化程序,然后检查 versionIdentifiers 属性,或使用 isConfiguration:compatibleWithStoreMetadata: 实例方法来确定兼容性。

于 2012-09-05T15:46:57.057 回答
2

将@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
于 2014-05-29T23:09:21.283 回答
0

斯威夫特版本。替换文件名。

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
    }
}
于 2017-02-07T09:17:16.157 回答
-2

不,无法预见这是可能的。NSManagedObjectModel 我从文档中推断出,它说讨论属性versionIdentifiers

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

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

于 2012-06-23T11:45:48.647 回答