iCloud使用UIDocument崩溃保存数据

时间:2012-08-13 01:31:04

标签: ios icloud uidocument

我正在尝试使用iCloud存储我的应用程序的userSetting,这是我的Save&加载代码:,它通常很好,但有时会崩溃,例如:尝试打开或还原已经在运行中打开或还原操作的文档发送到dealloc实例所以我添加fileState日志befere openWithCompletionHandler它总是显示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];
}

1 个答案:

答案 0 :(得分:1)

正如this question中所述,如果您的应用尝试紧密连续两次调用[document openWithCompletionHandler:]方法,则会出现错误。

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

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