0

我在我的应用程序中使用带有 iCloud 的 coredata。我正在使用几个在 iOS 6.1.3 下运行良好的代码,但在使用 iOS 6.1.3 设备时不能编写文档并保存。

我正在使用 OSX 10.8.3 和 xcode 版本:4.6.2

使用 iOS 6.1.3 时,执行在下面给出的代码处停止 -

[coordinator coordinateWritingItemAtURL:[managedDoc.persistentStoreOptions valueForKey:NSPersistentStoreUbiquitousContentURLKey] options:NSFileCoordinatorWritingForDeleting error:&logerror byAccessor:^(NSURL *newURL) {
    NSError * delError = nil;
    [[NSFileManager defaultManager] removeItemAtURL:newURL error:&delError];
    //if(delError)
        //NSLog(@"Error deleting transaction file .... , reason : %@",delError.localizedDescription); 
}];

整个代码如下:

-(void)saveManagegDocument{

if(iCloud){
NSError * error = nil;
[coordinator coordinateWritingItemAtURL:managedDoc.fileURL options:NSFileCoordinatorWritingForDeleting error:&error byAccessor:^(NSURL *newURL) {
    NSError * delError = nil;
    [[NSFileManager defaultManager] removeItemAtURL:newURL error:&delError];
    //if(delError)
        //NSLog(@"Error deleting data file .... , reason : %@",delError.localizedDescription); 
}];
NSError * logerror = nil;

[coordinator coordinateWritingItemAtURL:[managedDoc.persistentStoreOptions valueForKey:NSPersistentStoreUbiquitousContentURLKey] options:NSFileCoordinatorWritingForDeleting error:&logerror byAccessor:^(NSURL *newURL) {
    NSError * delError = nil;
    [[NSFileManager defaultManager] removeItemAtURL:newURL error:&delError];
    //if(delError)
        //NSLog(@"Error deleting transaction file .... , reason : %@",delError.localizedDescription); 
}];
}
[managedDoc saveToURL:managedDoc.fileURL 
     forSaveOperation:UIDocumentSaveForCreating 
    completionHandler:^(BOOL success) {
        if (success) {
            [managedDoc closeWithCompletionHandler:^(BOOL success) {
                [managedDoc openWithCompletionHandler:^(BOOL success) {
                    [self performSelectorOnMainThread:@selector(documentReady) withObject:nil waitUntilDone:NO];
                }];
            }];
        }
        else{
            [[[UIAlertView alloc] initWithTitle:@"Could not save or open core data database." message:nil delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil] show];
           // [self showMessage:@"Could not save or open core data database "];
            //NSLog(@"Could not save or open core data database ");
        }
    }];

}

任何人请帮助我。

并提前致谢。

4

1 回答 1

1

请参阅有关删除的文档,您将看到 NSFileManager 不是线程安全的,因此您希望在使用它调用 removeItemAtURL 时分配/初始化它的新实例。这可能会导致您看到执行停止的死锁。

您还需要确保在主线程之外运行此代码。我使用 GCD 来做到这一点。我删除文档的方法看起来像......

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
   NSAssert(![NSThread isMainThread], @"Must be not be on main thread");
   // insert code here 
});

当您使用异步块时,最好提供一个完成块,一旦异步块中的工作完成,就可以执行该完成块,这样您就可以安全地开始下一个操作。我看到您正在按顺序执行多个操作,即使它们是异步操作。最好将这些分解为不同的方法,然后与完成块协调。这是删除文档的示例方法。

- (void)deleteDocument:(UIDocument *)document withCompletionBlock:(void (^)())completionBlock {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

        NSError *fileCoordinatorError = nil;

        [[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:document.fileURL options:NSFileCoordinatorWritingForDeleting error:&fileCoordinatorError byAccessor:^(NSURL *newURL) {

            // extra check to ensure coordinator is not running on main thread
            NSAssert(![NSThread isMainThread], @"Must be not be on main thread");

            // create a fresh instance of NSFileManager since it is not thread-safe
            NSFileManager *fileManager = [[NSFileManager alloc] init];
            NSError *error = nil;
            if (![fileManager removeItemAtURL:newURL error:&error]) {
                NSLog(@"Error: %@", error);
                // TODO handle the error
            }

            if (completionBlock) {
                completionBlock();
            }
        }];
    });
}

然后你可以 deleteDocument 并给它一个完成块,它将在文档被删除后执行。您必须小心所有这些并发的发生。

一旦这个异步方法中的工作完成,它就可以从这里开始。

[self deleteDocument:document withCompletionBlock:^{
    // insert code for next action
}];

理论上 NSFileCoordinator 会处理这个问题,但它可能会在您的代码中的 [NSFileManager defaultManager] 上死锁。

让我知道这对你有什么影响。我一直在开发基于文档的应用程序,这是一个真正的挑战,因为有些事情是自动发生的,我还无法理解所有这些。但是由于我刚刚发现了这个死锁问题,我至少可以与您分享这段代码。

于 2013-05-12T20:43:48.020 回答