UIDocument closeWithCompletionHandler block never called (regression from iOS 5)

Number:rdar://12214822 Date Originated:8/31/12
Status:open Resolved:
Product:iOS SDK Product Version:6.0b4
Classification:other bug Reproducible:always
31-Aug-2012 09:55 AM Chris Adamson:
Completion handler block provided to -[UIDocument closeWithCompletionHandler:] is called on iOS 5, not on iOS 6

Steps to Reproduce:
Build the attached UIDocument-close-buglet-Recipes_01 project, which is an example from our upcoming "iOS SDK Development" book (http://pragprog.com/book/adios/ios-sdk-development) and has been built out over the course of several chapters. The app uses a UIDocument subclass to save user-created recipes. In this chapter, we use a unit test to make sure the persistence works as expected.

Here is the first part of a test method:
-(void) testPersistence2 {
  NSURL *docDir = [[[NSFileManager defaultManager]
                    inDomains:NSUserDomainMask] lastObject];
  NSURL *docURL = [docDir URLByAppendingPathComponent:@"Recipes.recipes"];
  PRPRecipesDocument *recipesDocForSaving = [[PRPRecipesDocument alloc] initWithFileURL:docURL];
  PRPRecipe *recipeToSave = [recipesDocForSaving createNewRecipe];
  STAssertNotNil(recipeToSave, @"Failed to create recipe from document");
  recipeToSave.title = NSLocalizedString(@"Nachos", nil);
  recipeToSave.directions = NSLocalizedString(@"Open bag\nOpen jar of salsa\nEnjoy", nil);
  recipeToSave.preparationTime = [NSNumber numberWithInt:1];
  [recipesDocForSaving recipesChanged];
  __block BOOL blockDone = NO;
  [recipesDocForSaving closeWithCompletionHandler:^(BOOL success) {
	NSLog (@"completion handler!");
    STAssertTrue(success, @"failed to save recipes doc");
    blockDone = YES;
  while (!blockDone) {
    [[NSRunLoop currentRunLoop] runUntilDate:
     [NSDate dateWithTimeIntervalSinceNow:0.1]];

This creates a document, creates a recipe object to be saved as part of the document, and sets its fields programmatically. It then closes the document with -[UIDocument closeWithCompletionHandler:], which takes a block to set a "blockDone" flag, which we then poll to hold the test until we know the document has been saved.

Expected Results:
When the test is run with Cmd-U in the RecipesUnitTests target (or, optionally, the Recipes target), the document is saved, the completion handler is called, and we can then attempt to read the document back in to continue our tests.

Actual Results:
The completion handler is never called, so the while block around runUntilDate runs forever. Set a breakpoint in the completion handler to confirm this: the breakpoint is never hit.

This code works as expected in iOS 5. Running in Xcode 4.5-DP4, you can run in the iPhone 5.1 simulator and the test will work, then switch to the iPhone 6 simulator and watch it hang.

Commented out in the code, you'll see our workaround: a 30-second wait. We've found that the document does eventually save, but it takes up to 30 seconds to do so, and the completion handler is never called.

31-Aug-2012 09:55 AM Chris Adamson:
'UIDOcument-close-buglet-Recipes_01.zip' was successfully uploaded


I didn't think that unit tests waited for completion blocks to be called. Are you sure this isn't just an issue with the unit testing setup?

By spencer.samuel1 at Nov. 28, 2013, 3:54 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!