2012-04-04 13 views
2

私は最初のiCloud Appで作業しています。しばらくの間働いた後、アプリケーションは "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:ドキュメントで呼び出されます。完了ブロックが呼び出されます。この後UIDocumentStateClosedと UIDocumentStateSavingError

:これは失敗し、UIDocumentStateChangedNotificationは5の文書の状態を示して発射されます。ここから進める正しい方法は何ですか?何が間違っていて、どのようなエラーが発生したのかを知る方法はありますか?

完了ブロックでドキュメントを再オープンしようとしましたが、結果は同じです。

私はファイルを削除して再作成するだけで問題を解決できると思います。しかし、アプリが店頭に出ると、これは明らかに選択肢にはならない。私は何がうまくいかないのかを知り、ユーザーに問題を処理するための適切な方法を与えたいと思います。

ここでUIDocumentStateSavingError(多くはありません)を扱う他の質問は既にチェックされていますが、ここで問題には当てはまらないようです。

どのように問題が発生しているかわかりますか?私は、APIがあなたに "保存中に何かが間違っていたが、何も教えてくれないだろう"と言っていることを信じることはできない。

答えて

5

完了ハンドラのdocumentStateを照会できます。 userInteractionPermitted:あなたが正確なエラーをしたい場合は残念ながら、それを得るための唯一の方法は、handleErrorのをサブクラス化し、オーバーライドすることである

たぶん、このようなものは、(コンパイラなしで入力されたフリーハンド)のに役立つだろう...

@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 
関連する問題