可以使用iCloud支持创建但不能打开UIManagedDocument

时间:2012-10-05 19:31:49

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

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

  1. 使用本地沙盒网址的Alloc和init
  2. 设置持久存储选项以支持iCloud:ubiquitousContentNameKey和ubiquitousContentURL。我正在生成唯一的名称,URL指向我的ubiquityContainer / CoreData。
  3. 使用UIManagedDocument的saveToURL方法在本地保存到沙箱。
  4. 在完成处理程序中,使用FileManager的setUbiquitous方法移至iCloud。
  5. 到目前为止,这种舞蹈有效。 (好吧,有点)。在我调用setUbiquitous之后,我收到一条错误消息,表示它没有成功,但文档会移动到云端。完成后,我在云端有一个新文档。这似乎是一个错误,因为我已经能够用别人的代码复制它。

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

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

    在此视图控制器中,我需要“重新打开”所选文档,以便用户可以对其进行编辑。

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

    1. 使用fileURL分配/初始化UIManagedDocument - 这次,URL来自云端。
    2. 使用相同的设置设置我的持久存储选项,与上面的步骤2相同。
    3. 现在,我尝试了第3步,即从磁盘打开文档,但它失败了。文档处于“已关闭|保存错误”状态,并且尝试打开失败。

      有谁知道为什么我的文档会创建好,移动到云可以,但是后续尝试无法打开? (真的,在应用程序启动时尝试 - 见下文)。具体来说,什么会使UIManagedDocument实例被创建但处于关闭,不可打开的状态?

      有趣的是,如果我退出应用并重新启动,我可以点按并重新加载文档并对其进行修改。

      偶尔我可以创建,然后打开,编辑非常简短,比如插入一个managedobject,然后它就会进入这个关闭状态。保存错误状态。

      错误信息:

      我已经将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:[Closed]

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

      2012-10-05 14:57:06.057基础[23687:5303] UIManagedDocument错误:商店名称:新文档34已在使用中。     商店网址:file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4〜com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore     使用商店网址: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。非同步/ 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];
          }
      
      }
      

2 个答案:

答案 0 :(得分:0)

您最近是否测试过各种版本的iOS?尝试将保存文档的标题更改为“新文档34”之外的其他内容,我遇到了同样的问题,我认为这与使用相同文档URL的应用程序的不同sdk编译保存的冲突文档有关。

答案 1 :(得分:0)

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

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

我的原始代码已创建,关闭,然后使用带有成功标准函数的回调重新打开文档。我在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;
            }

        }];

    }
}