ios - 在 iOS 7 中禁用 Core Data 中的 iCloud(也称为将持久存储文件迁移到本地)

标签 ios core-data ios7 core-data-migration

我正在使用新的 iOS 7 API 将核心数据与 iCloud 同步。这是一个非常简单直接的 API,但我找不到禁用它并再次使用本地存储的有效方法。没有数据丢失。

我正在像这样创建我的 iCloud persistantStore。它就像一个魅力。

[[context persistentStoreCoordinator] addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:[self iCloudFilePath]] options:@{ NSPersistentStoreUbiquitousContentNameKey: @"Favorite" } error:&error];

但是,我尝试使用新的迁移 API,将商店从 iCloud 商店迁移到本地商店,如下所示:

方法一使用*icloudps作为存储,方法二使用*ps作为存储。

NSPersistentStore *icloudps = [[[context persistentStoreCoordinator]
    persistentStores] objectAtIndex:0];

NSPersistentStore *ps = [[context persistentStoreCoordinator]
    addPersistentStoreWithType:NSSQLiteStoreType
    configuration:nil URL:[icloudps URL] options:nil error:&error];

[[context persistentStoreCoordinator] migratePersistentStore:icloudps
    toURL:[NSURL fileURLWithPath:[self filePath]]
    options:@{ NSPersistentStoreRemoveUbiquitousMetadataOption: @YES }
    withType:NSSQLiteStoreType error:&error];

方法 1 导致此崩溃:

Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xd000000000080002 x-coredata://153BBFEA-0319-4F10-AEA4-1DA12A21BFFF/Favorite/p2>''

方法二在此:

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'nil is not a valid persistent store'

我不知道如何让它工作。希望有人能提供帮助。

最佳答案

编辑

我刚刚发布了一个示例 iOS 库样式 Core Data 应用程序,其中包括 iCloud 集成。该应用程序包含一个设置包,供用户切换“使用 iCloud”首选项设置,并将根据用户设置将商店迁移到 iCloud 或从 iCloud 迁移。

从下面的链接下载 - 对文档感到抱歉 - 稍后会解决这个问题,但它的工作方式与 UIManagedDocument 示例大致相同。

http://ossh.com.au/design-and-technology/software-development/

编辑结束

如果有任何帮助的话,这里是我在 OS X 上使用的方法来保存 iCloud 同步核心数据文档的另一个副本(响应用户选择“另存为”菜单选项)。大多数情况下,iOS 应该以完全相同的方式工作。另请记住,迁移完成后您可能必须关闭并重新打开文档 - 如果我没有这样做,我似乎会想起一些问题。

/*! This method is used to build another local Core Data document, usually in response to the user selecting the 'Save As' menu option.  The document is NEVER iCloud enabled when we do this and the User can select the 'Share in iCloud' menu option once Save As is done to make the file available to other devices via iCloud.

    @param newURL The URL where the new file is to be created.
    @param typeName The type(SQLite, Binary or XML) of file to use for the new store.
    @param error  Upon return contains the error if one was encountered
    @return Returns YES if the new store was successfully created and NO if not.
 */
- (bool)buildNewStoreAtURL:(NSURL*)newURL type:(NSString *)typeName error:(NSError **)error {

    //FLOG(@"buildNewStoreAtURL:type:error: called");

    NSError *myError;

    // We only have one store so get it
    NSPersistentStore *currentStore = [self.managedObjectContext.persistentStoreCoordinator.persistentStores objectAtIndex:0];

    // Get any options it has, we assume we need to keep most of them
    NSDictionary *currentOptions = currentStore.options;

    NSMutableDictionary *newOptions = [[NSMutableDictionary alloc] initWithDictionary:currentOptions];

    // Make sure we don't use WAL mode, it has issues
    [newOptions setObject:@"DELETE" forKey:@"JOURNAL"];

    // Remove any iCloud options (this one includes the unique iCloud UUID)
    [newOptions removeObjectForKey:NSPersistentStoreUbiquitousContentNameKey];

    // Remove Core Data ubiquity metadata
    [newOptions setObject:[NSNumber numberWithBool:YES] forKey:NSPersistentStoreRemoveUbiquitousMetadataOption];

    NSPersistentStoreCoordinator *psc = self.managedObjectContext.persistentStoreCoordinator;

    // Now migrate the store to the new location
    NSPersistentStore *newStore = [psc migratePersistentStore:currentStore toURL:newURL options:newOptions withType:typeName error:&myError];

    // Now check it was successful
    if (newStore) {

        // Now set up our custom metadata so we can determine if it has been synced in iCloud next time we open it
        // We have to know this in order to pass in the correct options to the PSC
        NSDictionary *dict = [self getiCloudMetaDataForStore:[psc metadataForPersistentStore:newStore] iCloud:NO ubiquityName:nil];

        [psc setMetadata:dict forPersistentStore:newStore];

        return YES;
    }
    else {

        FLOG(@" problem creating new document");
        FLOG(@"  - error is %@, %@", myError, myError.userInfo);
        *error = myError;
        return NO;
    }

}

关于ios - 在 iOS 7 中禁用 Core Data 中的 iCloud(也称为将持久存储文件迁移到本地),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20293672/

相关文章:

swift - 如何返回基于许多核心数据实体的 NSObject 数组?

objective-c - (iOS, TheOS) %hook 到全局应用程序功能

iphone - 将 subview Controller 添加到 UINavigationController

cocoa-touch - 自动布局和 iOS7,以编程方式添加的 UIImageView 不会出现 - 似乎与线程相关

ios - 模拟位置,包括 Xcode 4.2/iOS5 中的移动

ios - XCode 为 iPad 构建应用程序但不允许调试

swift - 核心数据 : ValueTransformer functions are not called

ios - CoreData导入重载内存

ios - 设置位于 UICell 中的 UIButton 的标题

ios - 使用扩展创建可点击的 UIImageView