Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens under the hood when we do presentViewController?

Given the below code

self.view.backgroundColor = [UIColor yellowColor];
MyViewController *myVC = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil]
myVC.view.backgroundColor = [UIColor clearColor];
myVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:myVC animated:NO completion:nil];

What happens under the hood when we call presentViewController ? When myVC is visible I cannot see yellow color, then I checked myVC.view.superView in it's viewDidAppear method and it is UIWindow.

Q1. Is that mean until the modal window is up presentingViewController.view (self.view in above case) is removed from the View hierarchy and presentedViewController.view (myVC.view in above case) is added over UIWindow ?

Q2. What will be the case if myVC.modalPresentationStyle != UIModalPresentationFullScreen ?

Q3. Does iOS also remove all the views from UIWindow except presentedViewController.view until the full screen modal dialog is up for optimization ? If NO why not ?

like image 756
msk Avatar asked Apr 24 '13 13:04

msk


1 Answers

First, let's discuss the case without animation.

Before calling present:

  1. Your window has one view hierarchy, starting from its rootViewController view.

After calling present:

  1. The view hierarchy still exists without change.
  2. A special full-screen view called "dimming view" is added to the window (that is, not inside the rootViewController's view but inside the window (window is a UIView, too). This view is transparent, dims the presenting controler and blocks user interaction.
  3. The presented (modal) controller's view is then added also to the window.

There are some other views added in between the window and the presented controller's window. If you log your view hierarchy, you'll see classes named _ControllerWrapperView or something similar. However, this has changed between iOS versions and you shouldn't rely on the view structure. Note that that the modal controller can't ever be transparent because it is not direct subview of the window and the wrappers between the controller and the window are not transparent.

The animated case is almost the same. Only there are some fancy animations between the steps.

Edit 2: The answer was really a bit incorrect. There is a big difference between iPhone and iPad presented controllers.

On iPhone, the presented controllers are always displayed full screen and the presenting controllers are actually removed from the window.

On iPad, if the presented controller is not fullscreen (see UIModalPresentationStyle), the presenting controller stays in the window.

Your questions:

Is that mean until the modal window is up presentingViewController.view (self.view in above case) is removed from the View hierarchy and presentedViewController.view (myVC.view in above case) is added over UIWindow ?

If the controller is full screen, then this claim is true. Otherwise, the presenting view controller stays there but the whole contents are overlapped by other views (even if they are semi-transparent). Also, there are always some views between the presented and the presenting controller views.

What will be the case if myVC.modalPresentationStyle != UIModalPresentationFullScreen ?

See the answer to the previous question - on iPhone, there would be no difference.

Does iOS also remove all the views from UIWindow except presentedViewController.view until the full screen modal dialog is up for optimization ? If NO why not ?

From my tests, only the presenting controller is removed from the window hierarchy. This is probably to optimize drawing performance. This is the only controller the system can safely remove. Removing any other view could cause problems (e.g. views that should be always visible).

Edit: If you want to make a transparent controller, you can:

  1. Add the view directly to your view hierarchy (either to the controller's view or to the window) with a transition animation (+[UIView transition...])
  2. The same but also adding a child controller to your controller.
like image 124
Sulthan Avatar answered Sep 20 '22 20:09

Sulthan