将 Core Data/sqlite 记录迁移到新版本(从 Library 到 Documents 文件夹)

Posted

技术标签:

【中文标题】将 Core Data/sqlite 记录迁移到新版本(从 Library 到 Documents 文件夹)【英文标题】:Migrate CoreData/sqlite records into new version (from Library to Documens folder) 【发布时间】:2013-09-17 10:47:52 【问题描述】:

我完全重写了我之前由 3rd 方开发的应用程序。他们为 CoreData 使用了 Magical Record,我在模拟器上的 /Library/Application Support/AppName/ 文件夹中找到了他们的 appname.sqlite 文件。

我仍在学习 CoreData 并使用 Xcode 中的 CoreData 应用程序模板,我的 sqlite 位于 /Documents/ 文件夹中。有人可以建议打开旧商店的代码以便我执行迁移吗?谢谢。

原码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    [MagicalRecordHelpers setupCoreDataStack];
    .....
    return YES;

魔法记录:

+ (void) setupCoreDataStack

    NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
    [NSManagedObjectContext MR_setDefaultContext:context];



+ (void) MR_setDefaultContext:(NSManagedObjectContext *)moc

    NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_defaultStoreCoordinator];
    if ([MagicalRecordHelpers isICloudEnabled]) 
    
        [defaultManageObjectContext_ MR_stopObservingiCloudChangesInCoordinator:coordinator];
    

    MR_RETAIN(moc);
    MR_RELEASE(defaultManageObjectContext_);

    defaultManageObjectContext_ = moc;

    if ([MagicalRecordHelpers isICloudEnabled]) 
    
        [defaultManageObjectContext_ MR_observeiCloudChangesInCoordinator:coordinator];
    



+ (NSPersistentStoreCoordinator *) MR_defaultStoreCoordinator

    if (defaultCoordinator_ == nil && [MagicalRecordHelpers shouldAutoCreateDefaultPersistentStoreCoordinator])
    
        [self MR_setDefaultStoreCoordinator:[self MR_newPersistentStoreCoordinator]];
    
    return defaultCoordinator_;



+ (NSPersistentStoreCoordinator *) MR_newPersistentStoreCoordinator

    NSPersistentStoreCoordinator *coordinator = [self MR_coordinatorWithSqliteStoreNamed:[MagicalRecordHelpers defaultStoreName]];
    MR_RETAIN(coordinator);
    return coordinator;


+ (NSString *) defaultStoreName;

    NSString *defaultName = [[[NSBundle mainBundle] infoDictionary] valueForKey:(id)kCFBundleNameKey];
    if (defaultName == nil)
    
        defaultName = kMagicalRecordDefaultStoreFileName;
    
    if (![defaultName hasSuffix:@"sqlite"]) 
    
        defaultName = [defaultName stringByAppendingPathExtension:@"sqlite"];
    

    return defaultName;

编辑:

超越文件的代码:

- (void)migrateVersion1

    NSURL *version1URL = [[[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:@"Bundlename/Bundlename.sqlite"];

    NSManagedObjectModel *version1Model = [[NSManagedObjectModel alloc] initWithContentsOfURL:version1URL];

    NSPersistentStoreCoordinator *version1PCS;
    NSError *error = nil;

    if (version1Model != nil) 
    version1PCS = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:version1Model];
    

    if (![version1PCS addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:version1URL options:nil error:&error]) 
        // handle error
    

    NSManagedObjectContext *version1Context;
    if (version1PCS != nil) 
    version1Context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [version1Context setPersistentStoreCoordinator:version1PCS];
    

    // start parsing

【问题讨论】:

您是否真的更改了数据模型,或者只是您想要保存文件的位置?为什么要移动到 Documents 文件夹? 我确实改变了模型,但是模型本身并不复杂。我也扩展了它,所以对我来说最好的是阅读旧记录并在首次发布时将其存储到我的新模型中,然后忘记旧记录。我在创建新项目时使用 xcode 模板作为 coredata,模板将其存储在文档文件夹中。 您是否使用了版本化的托管对象模型?我希望你做到了,因为那样你就可以使用自动迁移。 IIRC,现代 Xcode 默认创建版本模型,因此它可能只是创建新版本并允许自动迁移的情况。 Appologies,但我仍在学习 CoreData,我的结论是我想首先避免使用 MagicalRecord。所以在这个阶段,我只需要一个建议如何连接到原始 sqlite 并解析它(我知道如何获取和解析它)。如果我需要对模型执行一些步骤,请也提出建议。非常感谢。 【参考方案1】:

方法一: 将现有的核心数据模型复制/移动到新的 XCode 项目中(您似乎又从头开始了)。选择模型,然后选择 Editor-->New Version。再次单击模型,然后在右侧菜单中选择新模型版本。对数据模型进行所需的微小更改。该应用程序应自动为您升级数据模型。

方法二: 将现有的核心数据模型复制/移动到新的 XCode 项目中。编写一个快速解析,获取先前模型中的所有对象,并在新模型中创建它们。确保不要混用 MOC。

方法 3 (Insanity.gif): 如果您无权访问以前版本的源代码……您将度过一段糟糕的时光。可以对核心数据 sqlite 文件进行逆向工程,但要知道 Apple 可能随时更改其工作方式。如果您查看表格,您会看到Z[name-of-object] 表格ZFOOZBAR 等... 一对一关系很容易通过表格中的列Z[relationship-name]ZMANAGER、@987654326 @ etc. One/Many-to-Many 将有一个表 Z_[number-from-metadata-for-obj1][name-of-obj-2] 例如Z_3ADDRESS 。与数据库中所有对象相比,与第一个对象的字母顺序相关的数字。是的。 Z_PK 是每个表的主键,在所有关系映射中用作参考。 Z_PrimaryKey 是调试多对多关系的指南,特别是 Z_ENT 列。

祝你好运

【讨论】:

我确实有原始来源,所以我选择方法 2。您能否建议代码打开原始 sqlite 并从中获取上下文?我显然在基础知识方面苦苦挣扎。我试图从我当前的 appDelegate 应用模型/psc/context 代码,但是当我尝试从 URL 初始化模型时,代码崩溃了。如果我找到如何编辑我的原始问题,我可以发布代码。 我让它最终工作。我的 migrate 方法的第二行是错误的。我应该使用模型 URL,例如: NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"OriginalDataModelName" withExtension:@"momd"];然后用这个ModelURL的内容初始化模型,显然不是sqlite文件。在此之后,它就像一个魅力。非常感谢大家!

以上是关于将 Core Data/sqlite 记录迁移到新版本(从 Library 到 Documents 文件夹)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 迁移至 SQLite 问题记录

将应用数据迁移到新的 IOS 应用

您将如何最小化或压缩 Core Data sqlite 文件大小?

如何 VACUUM 一个 Core Data SQLite 数据库?

备份和恢复 Core Data SQLite(核心数据)

sqlcipher与Microsoft.Data.Sqlite.Core踩坑