更新Core Data存储位置以支持应用程序组 [英] Update Core Data store location to support App Groups

查看:194
本文介绍了更新Core Data存储位置以支持应用程序组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我在App Store中已有一个使用核心数据保存数据的应用。

现在,当iOS 8即将推出时,我想添加一个窗口小部件,因此我必须使用应用程序组在二进制文件之间共享数据。

一个问题 - 我需要将商店位置更改为支持所有现有用户的应用程序组。
我写了以下代码,试图将存储移动到新路径:


I have an app already in the App Store that uses core data to save data.
Now, when iOS 8 is about to come out I wanna add a widget to it, thus I must use App Groups to share data between the binaries.
One problem though - I need to change the store location to support App Groups to all the existing users.
I wrote the following code, trying to move the store to the new path:

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *oldStoreURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    oldStoreURL = [oldStoreURL URLByAppendingPathComponent:@"Schooler.sqlite"];


    NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.schooler.mycontainer"];
    storeURL = [storeURL URLByAppendingPathComponent:@"Schooler.sqlite"];


    if([[NSFileManager defaultManager] fileExistsAtPath:oldStoreURL.path] == YES && [[NSFileManager defaultManager] fileExistsAtPath:storeURL.path] == NO)
    {
        // Prior today extension - Need to move to new directory
        NSError *error = nil;
        if([[NSFileManager defaultManager] moveItemAtURL:oldStoreURL toURL:storeURL error:&error] == YES)
            NSLog(@"Migrated successfully to new database location.");
        else
            NSLog(@"error: %@",error);
    }

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    return _persistentStoreCoordinator;
}

输出总是迁移成新数据库位置在应用程式之前储存的资料已删除,仿佛建立了新的资料库,而不是仅仅移动它。


是什么原因导致问题?我应该如何解决它?

谢谢。

The output is always "Migrated successfully to new database location.", although all the data that was saved on the app before has been deleted, As if it created a new database instead of just moving it.

What causes the problem? How should I fix it?
Thank you.

推荐答案

使用默认选项创建的Core Data NSSQLiteStoreType存储实际上是几个文件,如技术问答1809:新默认值中所述iOS 7和OS X Mavericks中的Core Data SQLite存储的日志模式。这是非常重要的记住,当尝试移动一个存储在外部迁移过程,并且是你的问题的根源 - 你移动一个文件,当你需要移动所有的。但是,不建议将文件单独移动到Core Data外部,而不建议使用文件协调器。最好使用迁移。

A Core Data NSSQLiteStoreType store created with the default options is actually several files, as described in Technical Q&A 1809: New default journaling mode for Core Data SQLite stores in iOS 7 and OS X Mavericks. This is important to remember when attempting to move a store outside of a migration process, and is the source of your issue - you are moving one file when you need to be moving all of them. Moving the files individually outside of Core Data and without the benefits of a file coordinator is not recommended, however. It's much better to use a migration instead.

迁移将从源存储获取数据,并将其迁移到新的存储位置,基本上在新位置复制旧数据。旧数据将仍然存在于文件系统上。在您的应用程序中,您应该像现在一样执行迁移,但不要尝试将旧数据自行移动到新位置 - 这是出现问题的地方。

A migration will take the data from the source store and migrate it to your new store location, essentially replicating the old data at the new location. The old data will still exist on the filesystem. In your application, you should perform the migration as you are now, but do not attempt to move the old data to the new location yourself - that is where things are going wrong.

您不需要移动自己周围的文件,而是可以依靠迁移来为您移动数据。首先,使用源数据的URL向永久存储协调器添加存储。然后您将执行迁移以将数据移动到新的URL

Instead of moving files around yourself, you can rely on a migration to move the data for you. First, add a store to the persistent store coordinator with the URL of the source data. Then you will perform a migration to move that data to the new URL

NSPersistentStore   *sourceStore        = nil;
NSPersistentStore   *destinationStore   = nil;
NSDictionary        *storeOptions       = @{ NSSQLitePragmasOption : @{ @"journal_mode" :
  @"WAL" } };

// Add the source store
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldStoreURL options:storeOptions error:&error]){
    // Handle the error
} else {
    sourceStore = [coordinator persistentStoreForURL:oldStoreURL];
    if (sourceStore != nil){
        // Perform the migration
        destinationStore = [coordinator migratePersistentStore:sourceStore toURL:storeURL options:storeOptions withType:NSSQLiteStoreType error:&error];
        if (destinationStore == nil){
            // Handle the migration error
        } else {
            // You can now remove the old data at oldStoreURL
            // Note that you should do this using the NSFileCoordinator/NSFilePresenter APIs, and you should remove the other files
            // described in QA1809 as well.
        }
    }
}

迁移完成后可以删除旧的文件。这里的示例明确指定了SQLite日志选项,这是为了确保如果默认选项在未来更改,代码仍然可以工作。如果您使用不同的选项,应该使用这些选项。

Once the migration has completed you can delete the old files. The example here explicitly specifies the SQLite journal options, this is to ensure that if the default options are changed in the future the code will still work. If you are using different options, you should use those instead.

这篇关于更新Core Data存储位置以支持应用程序组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆