3

我正在创建一个具有 iCloud 支持的新 UIManagedDocument,如下所示:

  1. 使用本地沙盒 URL 分配和初始化
  2. 设置持久存储选项以支持 iCloud:ubiquitousContentNameKey 和 ubiquitousContentURL。我唯一生成的名称和 URL 指向我的 ubiquityContainer / CoreData。
  3. 使用 UIManagedDocument 的 saveToURL 方法在本地保存到沙箱。
  4. 在完成处理程序中,使用 FileManager 的 setUbiquitous 方法移动到 iCloud。

到目前为止,这种舞蹈有效。(嗯,有点)。在我调用 setUbiquitous 后,我收到一个错误,说它不成功,但是文档移动到了云端。完成后,我在云中有一个新文档。这似乎是一个错误,因为我已经能够用其他人的代码复制它。

我实际上是在“文档视图控制器”中生成此文档,其中列出了云中的所有文档。因此,当这个新文档的最终完成处理程序完成时,由于 NSMetadataQuery,它会显示在表格视图中。到目前为止,我认为非常标准的用法。

要编辑文档,用户点击并转到“单视图文档视图控制器”。

在这个视图控制器中,我需要“重新打开”选定的文档,以便用户可以编辑它。

所以我再次经历了一系列步骤:

  1. 使用 fileURL 分配 / 初始化 UIManagedDocument —— 这次,URL 来自云端。
  2. 使用相同的设置设置我的持久存储选项,与上面的步骤 2 相同。

现在,我尝试了第 3 步,即从磁盘打开文档,但它失败了。文档处于“Closed | SavingError”状态并且尝试打开失败。

有谁知道为什么我的文档会创建 OK,移动到云 OK,但是在随后的立即尝试中无法打开?(实际上,在该应用程序的启动中进行了一次尝试 - 见下文)。具体来说,什么会使 UIManagedDocument 实例被创建但处于关闭、不可打开的状态?

有趣的是,如果我退出应用程序并再次启动,我可以点击并重新加载文档并进行编辑。

偶尔我可以很简单地创建、打开和编辑,比如插入一个托管对象,然后它进入关闭状态 | 保存错误状态。

错误信息:

我将 UIManagedDocument 子类化并覆盖了 -handleError: 方法以尝试获取更多信息,这就是我得到的(以及我放入的其他一些调试日志):

2012-10-05 14:57:06.000 基础 [23687:907] 单个文档视图控制器视图已加载。文档:fileURL:file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/documentState:[关闭]

2012-10-05 14:57:06.052 MyApp[23687:907] 文档状态已更改。当前状态:5 文件URL:file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState:[关闭 | 保存错误]

2012-10-05 14:57:06.057 Foundations [23687:5303] UIManagedDocument 错误:商店名称:新文档 34 已在使用中。存储 URL:file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore 正在使用存储 URL:file:/ /localhost/var/mobile/Applications/D423F5FF-4B8E-4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore

2012-10-05 14:57:06.059 MyApp[23687:5303] { NSLocalizedDescription = "商店名称:新文档 34 已在使用中。\n\t商店 URL:file://localhost/private/var/mobile/ Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n\t 使用商店 URL:file://localhost/var/mobile/Applications/D423F5FF-4B8E -4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n"; NSPersistentStoreUbiquitousContentNameKey = "新文档 34"; }

该错误似乎认为我正在创建一个在随后打开时已经存在的商店。我现在应该在第二次打开时在持久存储上设置这些 iCloud 选项吗?我已经尝试过这种方法,但它也没有奏效。

我研究了关于 UIManagedDocument 的斯坦福讲座,但看不出我做错了什么。

这是我创建文档并迁移到云的方法:

- (void) testCreatingICloudDocWithName:(NSString*)name
{

    NSURL* cloudURL = [self.docManager.iCloudURL URLByAppendingPathComponent:name isDirectory:YES];

    NSURL* fileURL = [self.docManager.localURL URLByAppendingPathComponent:name];


    self.aWriting = [[FNFoundationDocument alloc] initWithFileURL:fileURL];


    [self setPersistentStoreOptionsInDocument:self.aWriting];

    [self.aWriting saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
        if (success == YES) {

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                //create file coordinator
                //move document to icloud

                NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
                NSError* coorError = nil;
                [fileCoordinator coordinateWritingItemAtURL:cloudURL options:NSFileCoordinatorWritingForReplacing error:&coorError byAccessor:^(NSURL *newURL) {

                    if (coorError) {
                        NSLog(@"Coordinating writer error: %@", coorError);
                    }

                    NSFileManager* fm = [NSFileManager defaultManager];
                    NSError* error = nil;
                    NSLog(@"Before set ubiq");
                    [fm setUbiquitous:YES itemAtURL:fileURL destinationURL:newURL error:&error];
                    if (!error) {
                        NSLog(@"Set ubiquitous successfully.");
                    }
                    else NSLog(@"Error saving to cloud. Error: %@", error);


                    NSLog(@"State of Doc after error saving to cloud: %@", self.aWriting);
                }];



            });

        }
    }];

}

这是我在persistentStore上为iCloud设置选项的地方:

- (void)setPersistentStoreOptionsInDocument:(FNDocument *)theDocument
{
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    [options setObject:[theDocument.fileURL lastPathComponent] forKey:NSPersistentStoreUbiquitousContentNameKey];
    NSURL* coreDataLogDirectory = [self.docManager.coreDataLogsURL URLByAppendingPathComponent:[theDocument.fileURL lastPathComponent]];
    NSLog(@"Core data log dir: %@", coreDataLogDirectory);
    [options setObject:coreDataLogDirectory forKey:NSPersistentStoreUbiquitousContentURLKey];

    theDocument.persistentStoreOptions = options;
}

这是我尝试重新打开它的地方:

- (void) prepareDocForUse
{

    NSURL* fileURL = self.singleDocument.fileURL;

    if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
        NSLog(@"File doesn't exist");
            }
    else if (self.singleDocument.documentState == UIDocumentStateClosed) {
        // exists on disk, but we need to open it
        [self.singleDocument openWithCompletionHandler:^(BOOL success) {
            if (!success) {
                NSError* error;
                [self.singleDocument handleError:error userInteractionPermitted:NO];
            }
            [self setupFetchedResultsController];
        }];
    } else if (self.singleDocument.documentState == UIDocumentStateNormal) {
        // already open and ready to use
        [self setupFetchedResultsController];
    }

}
4

2 回答 2

0

我的目标是 iOS7,我使用单个 UIManagedDocument 作为我的应用程序数据库,目的是按照 Apple 在其文档中的建议更好地集成 CoreData 和 iCloud。我有同样的问题,我用下面的代码解决了。

自从我编写它以来,我将 PSC 选项设置移动到 UIManagedDocument 的惰性实例化中。

我的原始代码使用带有成功标准函数的回调创建、关闭然后重新打开文档。我在 Erika Sadun 的一本书上找到了它。一切似乎都很好,但我无法重新打开刚刚创建然后关闭的文档,因为它处于“保存错误”状态。我为此浪费了一周的时间,我无法理解我做错了什么,因为在重新开放之前一切都很完美。

以下代码在我的 iPhone5 和 iPad3 上完美运行。

尼古拉

-(void) fetchDataWithBlock: (void (^) (void)) fetchingDataBlock
{

    //If the CoreData local file exists then open it and perform the query
    if([[NSFileManager defaultManager] fileExistsAtPath:[self.managedDocument.fileURL path]]){
        NSLog(@"The CoreData local file in the application sandbox already exists.");

        if (self.managedDocument.documentState == UIDocumentStateNormal){
            NSLog(@"The CoreData local file it's in Normal state. Fetching data.");
            fetchingDataBlock();
        }else if (self.managedDocument.documentState == UIDocumentStateClosed){
            NSLog(@"The CoreData local file it's in Closed state. I am opening it.");

            [self.managedDocument openWithCompletionHandler:^(BOOL success) {
                if(success){
                    NSLog(@"SUCCESS: The CoreData local file has been opened succesfully. Fetching data.");
                    fetchingDataBlock();
                }else{
                    NSLog(@"ERROR: Can't open the CoreData local file. Can't fetch the data.");
                    NSLog(@"%@", self.managedDocument);
                    return;
                }
            }];
        }else{
            NSLog(@"ERROR: The CoreData local file has an unexpected documentState: %@", self.managedDocument);
        }
    }else{
        NSLog(@"The CoreData local file in the application sandbox did not exist.");
             NSLog(@"Setting the UIManagedDocument PSC options.");
        [self setPersistentStoreOptionsInDocument:self.managedDocument];

        //Create the Core Data local File
        [self.managedDocument saveToURL:self.managedDocument.fileURL
                       forSaveOperation:UIDocumentSaveForCreating
                      completionHandler:^(BOOL success) {

            if(success){

                NSLog(@"SUCCESS: The CoreData local file has been created. Fetching data.");
                fetchingDataBlock();

            }else{
                NSLog(@"ERROR: Can't create the CoreData local file in the application sandbox. Can't fetch the data.");
                NSLog(@"%@", self.managedDocument);
                return;
            }

        }];

    }
}
于 2013-11-19T17:00:58.430 回答
0

您最近是否在测试各种版本的 iOS?尝试将保存的文档的标题更改为“新文档 34”以外的名称,我遇到了同样的问题,我相信这与使用相同文档 url 从应用程序的不同 sdk 编译中保存的冲突文档有关。

于 2013-03-02T06:05:48.130 回答