3

我正在尝试使用 iCloud 来存储我的应用程序的 userSetting,这是我的 Save & Load Code: ,它通常运行良好,但有时会崩溃并显示如下消息:尝试打开或恢复已经在运行中打开或恢复操作的文档发送到 dealloc 实例,所以我在 openWithCompletionHandler 之前添加 fileState 日志,无论是否崩溃,它总是显示 state = UIDocumentStateClosed,我在 applecationDidEnterBackground 时保存数据并在 applicationDidBecomeActive 时加载。

节省:

-(void)storeToiCloud{
    NSURL *baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (baseURL) {
        NSURL *documentsURL = [baseURL URLByAppendingPathComponent:@"Documents"];
        NSURL *documentURL = [documentsURL URLByAppendingPathComponent:[NSString stringWithFormat:@"userSetting"]];
        if (!loadDocument) {
            self.loadDocument = [[MyUserDefaultsDocument alloc] initWithFileURL:documentURL];
        }
        loadDocument.myUserDefault = [MyUserDefaults standardUserDefaults];

        [loadDocument saveToURL:documentURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
        }];
    }
}

加载:

-(BOOL)shouldSynciCloud{
    if (![Utility iCloudEnable]) {
        return NO;
    }
    NSURL *baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (baseURL) {
        self.query = [[[NSMetadataQuery alloc] init] autorelease];
        [self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == 'userSetting'", NSMetadataItemFSNameKey];
        [self.query setPredicate:predicate];

        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self selector:@selector(queryDidFinish:) name:NSMetadataQueryDidFinishGatheringNotification object:self.query];

        [self.query startQuery];
        [Utility showSpinner];
        return YES;
    }
    return NO;
}

- (void)queryDidFinish:(NSNotification *)notification {
    NSMetadataQuery *query = [notification object];

    // Stop Updates
    [query disableUpdates];
    // Stop Query
    [query stopQuery];
    [query.results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        NSURL *documentURL = [(NSMetadataItem *)obj valueForAttribute:NSMetadataItemURLKey];

        if([[documentURL lastPathComponent] hasPrefix:@"userSetting"]){
            self.document = [[MyUserDefaultsDocument alloc] initWithFileURL:documentURL];
            NSString* message;
            if (document.documentState == UIDocumentStateNormal){
                message = @"UIDocumentStateNormal";
            }else if (document.documentState == UIDocumentStateClosed) {
                message = @"UIDocumentStateClosed";
            }else if(document.documentState == UIDocumentStateEditingDisabled){
                message = @"UIDocumentStateEditingDisabled";
            }else if(document.documentState == UIDocumentStateInConflict){
                message = @"UIDocumentStateInConflict";
            }else if(document.documentState == UIDocumentStateSavingError){
                message = @"UIDocumentStateSavingError";
            }
            NSLog(@"state = %@",message);
            [document openWithCompletionHandler:^(BOOL success) {
                if (success) {
                    MyUserDefaults *prefs = [MyUserDefaults standardUserDefaults];                    
                    NSData *book =[document.myUserDefault.realDict objectForKey:@"realbook"];
                    NSData *readSetting = [document.myUserDefault.realDict objectForKey:@"epubRS"];

                    if (book&&[[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudBook"]) {
                        [prefs setObject:book forKey:@"realbook"];
                        [Utility reloadRealBooks];
                    }
                    if (readSetting&&[[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudSetting"]) {
                        [prefs setObject:readSetting forKey:@"epubRS"];
                        [Utility setEpubReadSettingFromData:readSetting];
                    }
                    [prefs save];

                    [[NSNotificationCenter defaultCenter]postNotificationName:@"iCloudSynced" object:nil];
                    [Utility removeSpinner];
                }
                else{
                    [[NSNotificationCenter defaultCenter]postNotificationName:@"iCloudSyncfailed" object:nil];
                    [Utility removeSpinner];
                }
            }];
        }
    }];
    if ([query.results count]==0) {
        [[NSNotificationCenter defaultCenter]postNotificationName:@"iCloudSyncfailed" object:nil];
        [Utility removeSpinner];
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:nil];
}
4

1 回答 1

1

本问题所述,如果您的应用程序尝试连续两次调用 [document openWithCompletionHandler:] 方法,则会发生错误。

因为 openWithCompletionHandler: 是异步打开文档的,所以当再次调用该方法时,文档可能还在打开中。

如果发生这种情况,您的应用程序最终会尝试打开文档两次(因为文档状态将保持 UIDocumentStateClosed 直到完成),这会导致引发异常。

于 2012-09-13T20:09:45.090 回答