【问题标题】:Can create, but not open, a UIManagedDocument with iCloud support可以创建但不能打开具有 iCloud 支持的 UIManagedDocument
【发布时间】:2012-09-27 00:01:05
【问题描述】:

我正在创建一个支持 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 Foundations[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 已在使用中。 商店网址: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 = "商店名称:New Document 34 已在使用中。\n\tStore 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];
    }

}

【问题讨论】:

  • 这是在模拟器上吗?如果是,哪个 iOS 版本?我和其他人在 Xcode 中使用斯坦福代码的派生代码的 iOS 5.1 模拟器遇到了非常奇怪的问题
  • 这是 iOS 6 的设备。不幸的是,您无法在模拟器上测试 iCloud。
  • 我认为是 setUbiquitous 方法。不管 Apple 的文档怎么说,我认为在使用 UIManagedDocument 时没有必要。除非有人可以使用 ubiquityContainer URL 解释 setUbiquitous 和 saveToURL 之间的区别?当我只是将 toURL 保存到 iCloud 时,它似乎工作正常。
  • 您可以尝试在 setUbiquitous 上设置符号断点。我还没有达到这一点,但框架可能会发出调用似乎是合理的。
  • 你好杰森,我遇到了同样的问题!你修好了吗?

标签: objective-c ios core-data icloud uimanageddocument


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我的目标是 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;
                }
    
            }];
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-25
      • 1970-01-01
      • 2012-05-06
      • 2013-03-04
      • 1970-01-01
      • 2013-04-10
      • 1970-01-01
      • 2012-04-10
      • 2016-09-18
      相关资源
      最近更新 更多