Question

I have a UINavigationController, in which I push a view controller with a UIModalPresentationPageSheet presentation style.

From within this page sheet's view controller, I present a view controller with UIModalPresentationFormSheet style.

When the user hits a Done button the the form sheet, I want to close out the form sheet and the page sheet.

In the action on the Done button:

-(IBAction)onDone:(id)sender
{
  if(self->delegate && [self->delegate respondsToSelector:self->actionSelector])
  {
    [self->delegate performSelector:self->actionSelector withObject:[NSString stringWithString:self.textView.text]];
  }

  [self dismissViewControllerAnimated:YES completion:nil];
}

The delegate is the page sheet's view controller, and in the selector, I dismiss the page sheet:

[self dismissViewControllerAnimated:YES completion:nil];

When I run it, I get:

Warning: Attempt to dismiss from view controller <UINavigationController: 0xa9381d0> while a presentation or dismiss is in progress!

I can see why this is happening - because the selector is called before the form view is dismissed, but I don't know the best way around this.

I have tried removing the dismiss in onDone, and call dismiss for both in the selector call (with animated:NO for the form sheet), and it seems to function, but I don't know if this is the way that I should approach fixing it.

Was it helpful?

Solution

Try just calling dismissViewControllerAnimated:completion: on the page sheet. According to Apple's docs:

"If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack."

If that's not exactly the behavior you want, then you should use the completion handler argument in dismissViewControllerAnimated:completion: to pass in a block, then dismiss the other view controller from the completion handler, eg:

[formSheetViewController dismissViewControllerAnimated:YES completion:^{
    [pageSheetViewController dismissViewControllerAnimated:YES competion:nil];
}

Although really, I think just dismissing the page sheet should do the trick for you. It's still good to understand how completion handlers work. It lets you do some work after the operation is done--very handy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top