使用下一个App版本更新Core Data + iCloud模型

Mat*_*oal 3 migration upgrade core-data ios icloud

我必须处理使用Core Data和iCloud的下一个应用程序版本.iCloud已使用最"现代"的方式在当前版本中激活:

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:@"data_cfg"
                                                             URL:storeURL
                                                         options:@{NSPersistentStoreUbiquitousContentNameKey:@"theStore"}
                                                           error:&error]) 
Run Code Online (Sandbox Code Playgroud)

现在我需要更新商店结构,添加新的实体,关系等......

我完全陷入困境,因为我不知道更新模型的更好方法是知道iCloud与用户数据同步.

哪个是执行此类更新的最佳方式?我应该注意什么以及我最应该注意什么?如何迁移当前数据?

Tom*_*ton 5

使用iCloud时更新模型与不使用iCloud时相同 - 唯一的例外是您的更改必须是使用自动轻量级迁移的更改.Apple的文档详细描述了此类迁移的要求.基本步骤是:

  1. 创建数据模型的新版本,并使此版本为"最新".(你必须保持旧模型,所以现在你将有两个,但只有一个是最新的).
  2. 在新版本中更改模型.
  3. 添加NSMigratePersistentStoresAutomaticallyOptionNSInferMappingModelAutomaticallyOption对你的选择字典在上面的代码中,利用@YES作为两个值.

现在,当您启动应用程序时,Core Data将比较模型的旧版本和新版本(假设您的更改适用于自动轻量级迁移)修改持久性存储以使用新版本.

请记住,iCloud同步仅适用于使用相同版本数据模型的设备.如果用户在一台设备上升级您的应用程序而不是他们使用的另一台设备,则同步将停止,直到他们在其他设备上升级该应用程序.


l0g*_*g3r 5

iCloud Backup没关系,顺便提一下这里是安装新sqlite模型的解决方案.如果可以从服务器重新创建/下载应用程序内的数据,那么有一个很好的解决方案.您不需要设置迁移堆栈,有一个非常快速的解决方案.诀窍是删除旧的sqlite数据库并创建一个新的.

这是我在应用程序更新时使用的代码.您需要在AppDelegate.m中添加它

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"YourDatabase.sqlite"];
    NSManagedObjectModel *managedObjectModel = [self managedObjectModel];
    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel];

    // Check if we already have a persistent store
    if ( [[NSFileManager defaultManager] fileExistsAtPath: [storeURL path]] ) {
        NSDictionary *existingPersistentStoreMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType: NSSQLiteStoreType URL: storeURL error: &error];
        if ( !existingPersistentStoreMetadata ) {
            // Something *really* bad has happened to the persistent store
            //[NSException raise: NSInternalInconsistencyException format: @"Failed to read metadata for persistent store %@: %@", storeURL, error];
            NSLog(@"Failed to read metadata for persistent store %@: %@", storeURL, error);
        }

        if ( ![managedObjectModel isConfiguration: nil compatibleWithStoreMetadata: existingPersistentStoreMetadata] ) {
            if ( ![[NSFileManager defaultManager] removeItemAtURL: storeURL error: &error] )
                NSLog(@"*** Could not delete persistent store, %@", error);
        } // else the existing persistent store is compatible with the current model - nice!
    } // else no database file yet

    [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                              configuration:nil
                                                        URL:storeURL
                                                    options:nil
                                                      error:&error];
    return _persistentStoreCoordinator;
}

此代码涵盖问题

  • 如果现有数据库是旧数据库,则删除并设置新数据库.
  • 如果还没有数据库(用户只下载最新版本)而不是创建新数据库.
  • 如果现有数据库与新数据库兼容,只需使用它.

只需将@"YourDatabase.sqlite"更改为您的sqliteDB文件名,它就可以正常工作.

如果您的数据无法重新创建(从服务器同步),则需要设置迁移堆栈,
这是指向Apple指南的链接https://developer.apple.com/library/mac/Documentation/Cocoa/Conceptual/CoreDataVersioning /CoreDataVersioning.pdf