iOS 7 Completion handler never gets called

2019-04-12 12:09发布

问题:

In the following code none of the completion handlers ever get executed. The one explanation I was able to find is this Bug in iPhone Simulator 5.1 with Xcode 4.5 using UIManagedDocument . It says that it might be a bug in iPhone simulator 5.1 . However, I've tried iPhone simulators 6.0, 6.1 and 7.0, none of them worked. I'll really appreciate your help.

(By the way, I've seen this code in the Stanford iOS course, lecture 14)

NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"DataDocument"];
UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];

if(![[NSFileManager defaultManager] fileExistsAtPath:[url path]]){

        NSLog(@"This logs");

    [document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){

        NSLog(@"This never logs");

    }];

}else if(document.documentState == UIDocumentStateClosed){

        NSLog(@"This logs");
    [document openWithCompletionHandler:^(BOOL success){
        NSLog(@"This never logs");
    }];

}else{
    //I have a separate log for this, but it's never 'else'
}

EDIT: I've found a question that seems to be dealing with exactly the same problem. I Can't get an nsmanageobjectcontext I just pinned it down to the completion handler not being executed.

EDIT: I found out what the problem was: because openWithCompletionHandler executes asynchronously, my app would try to use the document before it finished opening. Using a run loop solved the problem. Example below.

if(doc.documentState == UIDocumentStateClosed){

    NSLog(@"This logs");
    __block BOOL waitingOnCompletionHandler = YES;
    [doc openWithCompletionHandler:^(BOOL success){

        NSLog(@"This logs too!");

    }];

    while (waitingOnCompletionHandler) {
       NSDate *futureTime = [NSDate dateWithTimeIntervalSinceNow:0.1];
       [[NSRunLoop currentRunLoop] runUntilDate:futureTime];
    }

}