presentModalViewController from UIModalTransitionStylePartialCurl viewController

Keller picture Keller · Jan 6, 2012 · Viewed 11.7k times · Source

I have a modal view that is presented via UIModalTransitionStylePartialCurl transition. In that modal view there is a button, which I would like to:

  1. dismiss the current modal view (curl down), then
  2. present a new modal view (cover vertical).

However, when I try the following, it simply dismisses the curl modal view but doesn't present the new one:

[self dismissModalViewControllerAnimated:YES];
NewView *vc = [[NewView alloc] init];
[self.parentViewController presentModalViewController:vc animated:YES];

I have a feeling it has to do with that last line. Presenting NewView on self doesn't work either. How can I accomplish this?

Answer

Tyson Tune picture Tyson Tune · Jan 6, 2012

Are you using iOS 5?

If so the problem you are seeing is due to a change documented here: http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instp/UIViewController/parentViewController

The important bit at that link is this:

Prior to iOS 5.0, if a view did not have a parent view controller and was being presented modally, the view controller that was presenting it would be returned. This is no longer the case. You can get the presenting view controller using the presentingViewController property.

So changing to self.presentingViewController may fix your issue, but probably will not.

Using this code from your first modal:

[self dismissModalViewControllerAnimated:YES];
SecondViewController *sec = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
sec.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self.presentingViewController presentModalViewController:sec animated:YES];

You don't see the new view controller presented.

To get what you are after you want to use a new (as of iOS5) method:

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion

This method is the recommended replacement for presentModalViewController.

And a custom method on your first view controller, something like:

- (void)cycleModalViewControllersWithController:(UIViewController *)newViewController

That method can both dismiss your current modal and present the new one, something like this:

- (void)cycleModalViewControllersWithController:(UIViewController *)newViewController {
    [self dismissViewControllerAnimated:YES completion:^{
        [self presentViewController:newViewController animated:YES completion:NULL]; 
    }];
}

Using the completion block to launch the new modal let's you wait until the old modal has animated out. So in your second modal view controller you would call your custom method on your first modal view controller and let it manage dismissing/presenting the new one.