当我们执行presentViewController时会发生什么?

msk*_*msk 14 iphone objective-c uiviewcontroller ipad ios

鉴于以下代码

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];
Run Code Online (Sandbox Code Playgroud)

当我们调用presentViewController时会发生什么?当myVC可见时,我看不到黄色,然后我在它的viewDidAppear方法中检查了myVC.view.superView,它是UIWindow.

Q1.这意味着,直到模态窗口向上呈现ViewController.view(上面的情况中的self.view)从View层次结构中移除并且在UIWindow上添加了presentViewController.view(上面的情况中的myVC.view)?

Q2.如果myVC.modalPresentationStyle!= UIModalPresentationFullScreen会是什么情况?

Q3.除了presentViewController.view之外,iOS还会删除UIWindow中的所有视图,直到全屏模式对话框进行优化吗?如果不是为什么不呢?

Sul*_*han 18

首先,让我们讨论没有动画的情况.

致电之前present:

  1. 您的窗口具有一个视图层次结构,从rootViewController视图开始.

打电话后 present:

  1. 视图层次结构仍然存在而没有更改.
  2. 一个称为"调光视图"的特殊全屏视图被添加到窗口中(即,不在rootViewController视图内部但在窗口内部(窗口也是a UIView).此视图是透明的,使呈现控制器变暗并阻止用户相互作用.
  3. 然后将呈现的(模态)控制器视图添加到窗口中.

在窗口和显示的控制器窗口之间添加了一些其他视图.如果您记录视图层次结构,您将看到命名的类_ControllerWrapperView或类似的类.但是,这在iOS版本之间已经发生了变化,您不应该依赖于视图结构.请注意,模态控制器不能是透明的,因为它不是窗口的直接子视图,并且控制器和窗口之间的包装器不透明.

动画案例几乎相同.只有步骤之间有一些奇特的动画.

编辑2: 答案真的有点不对劲.iPhone和iPad呈现的控制器之间存在很大差异.

在iPhone上,显示的控制器始终全屏显示,实际控制器实际上已从窗口中删除.

在iPad上,如果显示的控制器不是全屏(请参阅参考资料UIModalPresentationStyle),则显示控制器会保留在窗口中.

你的问题:

这意味着,直到模态窗口向上呈现ViewController.view(上面的情况中的self.view)从View层次结构中移除并且在UIWindow上添加了presentViewController.view(上面的情况中的myVC.view)?

如果控制器是全屏的,那么这种说法是正确的.否则,呈现视图控制器保持在那里但整个内容与其他视图重叠(即使它们是半透明的).此外,在呈现的控制器视图和呈现的控制器视图之间总是存在一些视图.

如果myVC.modalPresentationStyle!= UIModalPresentationFullScreen会是什么情况?

看到上一个问题的答案 - 在iPhone上,没有区别.

除了presentViewController.view之外,iOS还会删除UIWindow中的所有视图,直到全屏模式对话框进行优化吗?如果不是为什么不呢?

从我的测试中,只有呈现控制器从窗口层次结构中删除.这可能是为了优化绘图性能.这是系统可以安全删除的唯一控制器.删除任何其他视图可能会导致问题(例如,应始终可见的视图).

编辑: 如果要制作透明控制器,您可以:

  1. 使用过渡动画(+[UIView transition...])将视图直接添加到视图层次结构(控制器视图或窗口)
  2. 同样但也为控制器添加了一个子控制器.

  • 这个答案有点不正确.当呈现模态全屏幕控制器时,UIKit会从窗口中删除其他控制器的视图.事实上,从窗口添加/删除正是`-viewDid/Will(Dis)出现的:`方法正在报告.但在你回到它们之前,UIKit会将它们添加回窗口. (2认同)