core-data - UIManagedDocument - 如何处理 UIDocumentStateSavingError?

标签 core-data icloud uimanageddocument

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

这是我创建 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

在此之后,完成 block 被调用。从这里开始的正确方法是什么?有什么办法可以查出出了什么问题以及发生了什么样的错误吗?

我尝试在完成 block 中重新打开文档,但结果是相同的。

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

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

知道如何找出问题所在吗?我不敢相信 API 会告诉您“保存期间出了点问题,但我不会告诉您是什么!”

最佳答案

您可以在完成处理程序中查询 documentState。不幸的是,如果您想要确切的错误,获得它的唯一方法是子类化并重写handleError:userInteractionPermission:

也许这样的东西会有所帮助(无需编译器徒手输入)...

@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];
                });
            }
        }];                    

关于core-data - UIManagedDocument - 如何处理 UIDocumentStateSavingError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10015950/

相关文章:

ios - 如何检查关系是否已经建立 - Core Data

core-data - 我应该在 UIManagedDocument 中使用 NSFileWrappers 吗?

ios - 在核心数据中使用 UIManagedDocument 的标准(或正确)方法是什么

ios - '+实体名称 : nil is not a legal NSManagedObjectContext parameter searching for entity name 'Movie' '

ios - 删除核心数据中一个属性等于另一个属性的记录

swift - NSBatchDeleteResult - 不接受任何参数

ios - iCloud 无处不在的容器在删除应用程序时没有被清理?

ios - 如何通知另一台设备 CloudKit 记录已更新?

ios - Xcode 没有为 iCloud 和 CloudKit : "Add the iCloud containers entitlement to your App ID" fails 创建默认容器

objective-c - 当条目更新但未保存时,核心数据会重复