22

update:
I've faced this problem again, and found another way. If presenting controller is not embedded in navigation controller, it will be hidden if presented controller is not fullscreen and will became black. Method setModalPresentationStyle:UIModalPresentationCurrentContext can be applied only to navigation controller. So embed presenting controller in UINavigationController, set UIModalPresentationCurrentContext to it and present new controller - you will get dialog controller.

I'm presenting search controller, it have tableView that push on stack detailed controller.

Detailed controller can present view controller with message, it consists from small UIView and semitransparent background.

Problem: when last view controller presented, all view controllers under it becomes hidden and controller, that presented search controller becomes visible.

Here what I'm doing:

SearchViewController *viewController = [[SearchViewController alloc] initWithNibName:@"SearchViewController" bundle:nil];
viewController.data = dataArray;

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[self.navigationController setModalPresentationStyle:UIModalPresentationCurrentContext];
[self.navigationController presentViewController:navigationController animated:YES completion:nil];

than table pushes detailed view:

DetailViewController *viewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
[viewController setHidesBottomBarWhenPushed:YES];
viewController.dataItem = [data objectAtIndex:(NSUInteger) [indexPath row]];
[self.navigationController pushViewController:viewController animated:YES];

and detailed view presenting message box:

MessageController *controller = [[MessageController alloc] initWithNibName:@"MessageController" bundle:nil];
controller.message = message;
[self presentViewController:controller animated:YES completion:nil];

When it's dismissed, all controllers under it became visible.

update:

all I wanted is to present modally a view controller that will have uitableview. From this table to show detailed view that will be able to show message box. Message box must be another view controller. And when message box is shown all two preceding controllers disappears. that is the issue.

trickster77777
  • 1,198
  • 2
  • 19
  • 30
  • 2
    It's very hard to follow what it is you are describing as the issue as well as what you want it to do. Suggest you add a screen shot or picture to better describe the problem you'd like help with. – Bladebunny Nov 02 '13 at 16:55

6 Answers6

20

In some situations, you could have each modally presented view controller present the next one.

let window = UIApplication.sharedApplication().keyWindow!
if let modalVC = window.rootViewController?.presentedViewController {
    modalVC.presentViewController(vc, animated: true, completion: nil)
} else {
    window.rootViewController!.presentViewController(vc, animated: true, completion: nil)
}
SlimeBaron
  • 645
  • 8
  • 17
12

Dismiss all view controllers above the presented view controller.

Apple's documentation follows:

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.

Dismiss two modal view controllers.

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:NULL];

https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#jumpTo_51

AmitaiB
  • 1,656
  • 1
  • 19
  • 19
Rei Kubonaga
  • 169
  • 1
  • 5
  • There is no such text in the documentation. Please update you answer – Kostiantyn Koval Sep 24 '15 at 08:18
  • @KostiantynKoval it's definitely there: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/dismissViewControllerAnimated:completion: – chedabob Jan 08 '16 at 21:42
  • The documentation is here: https://developer.apple.com/reference/uikit/uiviewcontroller/1621505-dismissviewcontrolleranimated. I don't believe that the documentation is correct though; it seems that the top-most view as well as intermediate lower views get dismissed without animation and then the view on which `dismissViewControllerAnimated:` was called gets dismissed with animation – Josh Gafni Apr 18 '17 at 21:30
  • I am not sure what the author meant and why other users up voted it but let me tell you what I've tested: I am presenting VC1 as modal from MainVC. Afterwards I am presenting VC2 from VC1 also as modal. A few seconds later I dismiss VC1 and VC2 stays the same without any change. it's worth mentioning that VC1 and VC2 have an embedded NavBar but again, both are presented as modal and NOT push to stack. – OhadM Dec 20 '19 at 14:11
10

This answer might seem a little unconventional, but it works. It lets you "open multiple modals", but only show one at a time. The key is to have just one modal, but use a Tab Bar Controller to switch between View Controllers.

multiple modals

  1. Wire your modal segue from the blue (presenting) View Controller to a modal container (which is just a regular View Controller)
  2. The modal container holds just a Container View, whose sole purpose is to embed a Tab Bar Controller.
  3. Embed a Tab Bar Controller inside the Container View
  4. Each tab can be a separate View Controller, representing "multiple modals"
  5. Set the Tab Bar Controller's Tab Bar to hidden
  6. Switch between modals using tabBarController?.selectedIndex = 1
  7. Close the modal normally with dismissViewControllerAnimated(true, completion: nil)

It would look something like this:

enter image description here

Robert Chen
  • 5,179
  • 3
  • 34
  • 21
5

The trivial way to attempt to achieve that is to just create the VCs you want to present modally and present one after the other. Unfortunately, this is not gonna work. What you get is just the first VC presented, all others just go nowhere. UIKit just won’t cooperate with you here.

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Michal Šrůtek
  • 1,647
  • 16
  • 17
Gtx
  • 231
  • 1
  • 10
  • 17
  • 4
    It seems like a better way to do this now (instead of using an image) is to set `self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext` before presenting the view controller, and then reset the value in the completion handler. See http://stackoverflow.com/a/15794051/339925 – Paul Young Mar 14 '14 at 14:29
1

Set the correct modalPresentationStyle on both the navigationController AND the viewController itself.

self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
vcToPresent.modalPresentationStyle = UIModalPresentationFormSheet;
vcToPresent.preferredContentSize = CGSizeMake(650, 450);

[self presentViewController:vcToPresent animated:YES completion:^{
    self.navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
}];`
rizzes
  • 1,532
  • 20
  • 33
1

I found a solution: provide your own custom animation:

    let transition: CATransition = CATransition()
    transition.duration = 0.5
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = kCATransitionReveal
    transition.subtype = kCATransitionFromBottom
    self.view.window!.layer.add(transition, forKey: nil)
    self.presentingViewController?.presentingViewController?.dismiss(animated: false, completion: nil)
Antzi
  • 12,831
  • 7
  • 48
  • 74