2012-04-04 57 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