2012-04-04 55 views
2

我正在开发我的第一个iCloud应用程序。在工作了一段时间之后,由于“UIDocumentStateSavingError”,应用程序无法再访问UIManagedDocument。有什么方法可以真正找出发生了什么错误?UIManagedDocument - 如何处理UIDocumentStateSavingError?

这是我的代码来创建UIManagedDocument:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    iCloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 

    if (iCloudURL == nil) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self iCloudNotAvailable]; 
     }); 
     return; 
    } 


    iCloudDocumentsURL = [iCloudURL URLByAppendingPathComponent:@"Documents"]; 
    iCloudCoreDataLogFilesURL = [iCloudURL URLByAppendingPathComponent:@"TransactionLogs"]; 

    NSURL *url = [iCloudDocumentsURL URLByAppendingPathComponent:@"CloudDatabase"]; 
    iCloudDatabaseDocument = [[UIManagedDocument alloc] initWithFileURL:url]; 

    NSMutableDictionary *options = [NSMutableDictionary dictionary]; 

    NSString *name = [iCloudDatabaseDocument.fileURL lastPathComponent]; 
    [options setObject:name forKey:NSPersistentStoreUbiquitousContentNameKey]; 
    [options setObject:iCloudCoreDataLogFilesURL forKey:NSPersistentStoreUbiquitousContentURLKey]; 

    iCloudDatabaseDocument.persistentStoreOptions = options; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentContentsChanged:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:iCloudDatabaseDocument.managedObjectContext.persistentStoreCoordinator]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentStateChanged:) name:UIDocumentStateChangedNotification object:iCloudDatabaseDocument]; 


    if ([[NSFileManager defaultManager] fileExistsAtPath:[iCloudDatabaseDocument.fileURL path]]) { 
     // This is true, the document exists. 
     if (iCloudDatabaseDocument.documentState == UIDocumentStateClosed) { 
      [iCloudDatabaseDocument openWithCompletionHandler:^(BOOL success) { 
       if (success) { 
        dispatch_async(dispatch_get_main_queue(), ^{ 
         [self documentConnectionIsReady]; 
        }); 
       } else { 
        dispatch_async(dispatch_get_main_queue(), ^{ 
         [self connectionError:iCloudConnectionErrorFailedToOpen]; 
        }); 
       } 
      }];      
     } else if (iCloudDatabaseDocument.documentState == UIDocumentStateNormal) { 
      ... 
     }  
    } else { 
     ...    
    }   
}); 

文件已经存在,因此openWithCompletionHandler:被称为上的文档。这种失败,UIDocumentStateChangedNotification被激发,显示的5文件规定: UIDocumentStateClosed和 UIDocumentStateSavingError

此完成块被调用后。从这里出发的正确方法是什么?有什么方法可以找出哪里出了问题,发生了什么样的错误?

我试图重新打开完成块中的文档,但结果是一样的。

我想我可以通过删除文件并重新创建它来解决问题。但是,一旦应用程序将在商店中出现,这显然不是一种选择。我想知道发生了什么问题,并为用户提供一种解决问题的方法。

我已经在这里检查了其他问题,处理UIDocumentStateSavingError(这里没有很多),但似乎不适用于这里的问题。

任何想法如何找出问题所在?我无法相信API告诉你“保存期间出现问题,但我不会告诉你什么!”

回答

5

您可以在完成处理程序中查询documentState。不幸的是,如果你想确切的错误,只有这样,才能得到它是继承并重写的HandleError:userInteractionPermitted:

也许会有这样的帮助(没有编译器类型写意)...

@interface MyManagedDocument : UIManagedDocument 
- (void)handleError:(NSError *)error 
     userInteractionPermitted:(BOOL)userInteractionPermitted; 
@property (nonatomic, strong) NSError *lastError; 
@end 

@implementation MyManagedDocument 
@synthesize lastError = _lastError; 
- (void)handleError:(NSError *)error 
     userInteractionPermitted:(BOOL)userInteractionPermitted 
{ 
    self.lastError = error; 
    [super handleError:error 
      userInteractionPermitted:userInteractionPermitted]; 
} 
@end 

然后,你可以这样创建它...

iCloudDatabaseDocument = [[UIManagedDocument alloc] initWithFileURL:url]; 

,并在这样的完成处理程序使用它...

 [iCloudDatabaseDocument openWithCompletionHandler:^(BOOL success) { 
      if (success) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [self documentConnectionIsReady]; 
       }); 
      } else { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [self connectionError:iCloudConnectionErrorFailedToOpen 
           withError:iCloudDatabaseDocument.lastError]; 
       }); 
      } 
     }];      
1

基于@JodyHagins的优秀片段,我制作了一个UIDocument子类。

@interface SSDocument : UIDocument 
- (void)openWithSuccess:(void (^)())successBlock 
      failureBlock:(void (^)(NSError *error))failureBlock; 
@end 


@interface SSDocument() 
@property (nonatomic, strong) NSError *lastError; 
@end 

@implementation SSDocument 

- (void)handleError:(NSError *)error userInteractionPermitted:(BOOL)userInteractionPermitted { 
    self.lastError = error; 
    [super handleError:error userInteractionPermitted:userInteractionPermitted]; 
} 

- (void)clearLastError { 
    self.lastError = nil; 
} 

- (void)openWithSuccess:(void (^)())successBlock failureBlock:(void (^)(NSError *error))failureBlock { 
    NSParameterAssert(successBlock); 
    NSParameterAssert(failureBlock); 
    [self clearLastError]; 
    [self openWithCompletionHandler:^(BOOL success) { 
     if (success) { 
      successBlock(); 
     } else { 
      NSError *error = self.lastError; 
      [self clearLastError]; 
      failureBlock(error); 
     } 
    }]; 
} 

@end