将 iOS 应用程序转换为全新的核心数据数据模型

Posted

技术标签:

【中文标题】将 iOS 应用程序转换为全新的核心数据数据模型【英文标题】:Transitioning iOS app to completely new core data data model 【发布时间】:2013-10-15 03:45:56 【问题描述】:

我继承了一个需要进行重大更改的 ios 应用。在其当前形式中,它使用单个 UIManagedDocument(未与 iCloud 同步,但仅用于避免 Core Data 样板)来存储用户数据。我需要对数据模型进行重大更改,并且我想切换到普通的 Core Data 堆栈。现有的代码库也非常不可用,所以我决定创建一个新项目,但使用相同的应用 ID,以便它可以作为更新发布。

我不确定如何将现有用户的数据导入新的数据模型。

当前模型有 3 个主要实体,我只需要它们中的 2 个属性(其余的旧数据可能会被丢弃)。我已经创建了新的数据模型,然后我从以前的项目中复制了所有旧模型文件以及旧数据模型。

然后我写了一个导入器类:

-(BOOL)isImportNeeded

    return [[NSFileManager defaultManager] fileExistsAtPath:[[self URLToOldModel] path]];


-(NSURL*)URLToOldModel

    NSURL* URL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    return [URL URLByAppendingPathComponent:@"Data"];


-(UIManagedDocument*)managedDocumentAtPath:(NSString*)path

    return [[UIManagedDocument alloc] initWithFileURL:[self URLToOldModel]];


-(void)performWithDocument:(void (^)(void))onDocumentReady

    if (self.managedDoc.documentState == UIDocumentStateClosed) 
        // I put this code here for debug purposes
        NSError* e = nil;
        if (![self.managedDoc readFromURL:self.managedDoc.fileURL error:&e]) 
            NSLog(@"Couldn't read UIManagedDocument: %@", [e localizedDescription]);
        
//        [self.managedDoc openWithCompletionHandler:^(BOOL success)
//            if (success)
//                onDocumentReady();
//            else
//                NSLog(@"Could not open document");
//        ];
    
    else if (self.managedDoc.documentState == UIDocumentStateNormal)
    
        onDocumentReady();
    


-(void)import

    self.managedDoc = [self managedDocumentAtPath:[[self URLToOldModel] path]];
    self.sourceManagedObjectContext = self.managedDoc.managedObjectContext;

    [self performWithDocument:^ ... ];

NSLog 打印出以下内容:Couldn't read UIManagedDocument: The operation couldn’t be completed. (Cocoa error 134100.) 深入研究错误的 userInfo 字典,我认为这是错误原因:“用于打开商店的模型与用于打开商店的模型不兼容创建商店”。

我已确保旧数据模型已添加到项目中,并且处于“编译源”构建阶段。

我了解了有关 UIManagedDocument 的更多信息,并意识到当它被初始化时,它会自动创建捆绑中所有数据模型的联合,而阻止这种情况的方法是继承 UIManagedDocument 并覆盖 managedObjectModel 访问器。我这样做了,只使用以下方法创建了一个子类:

-(NSManagedObjectModel*)managedObjectModel

    NSString* modelPath = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"momd"];
    modelPath = [modelPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL* modelURL = [NSURL URLWithString:modelPath];
    return [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

但是,我仍然遇到同样的错误。

【问题讨论】:

【参考方案1】:

我的一个朋友提出了这个建议,我在我从事过的每一个核心数据应用程序中都使用了这个 - 不知道它是如何逃脱我的:

self.managedDoc.persistentStoreOptions = @NSIgnorePersistentStoreVersioningOption: @YES,
                                           NSMigratePersistentStoresAutomaticallyOption: @YES,
                                           NSInferMappingModelAutomaticallyOption: @YES;

做到了。

【讨论】:

以上是关于将 iOS 应用程序转换为全新的核心数据数据模型的主要内容,如果未能解决你的问题,请参考以下文章

将核心数据迁移到一个干净的开始

在核心数据中进行大量迁移后尝试保存数据

IOS/xcode:将核心数据从应用委托移动到模型类

将核心数据中的 NSNumber 转换为 NSString

如何将数据从 iOS 中的数据模型存储到核心数据中并以数据模型的格式获取

核心数据迁移:无法将“NSManagedObject_MyType”类型的值转换为“MyModule.MyType”