【问题标题】:What happens under the hood when we do presentViewController?当我们执行 presentViewController 时,幕后会发生什么?
【发布时间】:2013-04-18 01:43:47
【问题描述】:

给定以下代码

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];

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

Q1. 这是否意味着直到模态窗口启动为止,presentingViewController.view(在上述情况下为 self.view)从视图层次结构中移除,并从 presentingViewController.view(在上述情况下为 myVC.view)在 UIWindow 上添加?

Q2.如果 myVC.modalPresentationStyle != UIModalPresentationFullScreen 会怎样?

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

【问题讨论】:

  • 什么是clippingVC

标签: iphone ios objective-c ipad uiviewcontroller


【解决方案1】:

首先,我们来讨论一下没有动画的情况。

致电present之前:

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

致电present:

  1. 视图层次结构仍然存在,没有变化。
  2. 一个特殊的全屏视图被添加到窗口中(即不在rootViewController的视图内,而是在窗口内(窗口也是UIView)。这个视图是透明,使呈现控制器变暗并阻止用户交互。
  3. 呈现的(模态)控制器的视图随后也会添加到窗口中。

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

动画案例几乎相同。只是步骤之间有一些花哨的动画。

编辑 2: 答案确实有点不正确。 iPhone 和 iPad 提供的控制器之间存在很大差异。

在 iPhone 上,呈现的控制器始终全屏显示,而呈现的控制器实际上已从窗口中移除。

在 iPad 上,如果呈现的控制器不是全屏的(请参阅 UIModalPresentationStyle),呈现的控制器会停留在窗口中。

您的问题:

这是否意味着直到模态窗口启动才将presentingViewController.view(上例中的self.view)从视图层次结构中删除,并在UIWindow上添加presentingViewController.view(上例中的myVC.view)?

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

如果 myVC.modalPresentationStyle != UIModalPresentationFullScreen 会怎样?

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

iOS 是否也会从 UIWindow 中删除所有视图,除了presentedViewController.view 直到全屏模式对话框进行优化?如果没有,为什么不呢?

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

编辑: 如果你想做一个透明的控制器,你可以:

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

【讨论】:

  • 这个答案有些不正确。当呈现模态全屏控制器时,UIKit 会从窗口中移除其他控制器的视图。事实上,从窗口中添加/删除正是-viewDid/Will(Dis)appear: 方法报告的内容。但是 UIKit 在你返回它们之前会将它们添加回窗口。
  • @BJHomer 你是对的。我主要有 iPad 的经验,所以我在 iPhone 的情况下弄错了。修正了答案。
  • 这也是来自我的实验 -> “只有呈现控制器从窗口层次结构中删除”。我希望 iOS 永远不能从窗口层次结构中删除所有其他视图。 @BJ Homer 说“当呈现模态全屏控制器时,UIKit 会从窗口中删除其他控制器的视图”是错误的。
  • 好吧,让我们这样说吧。当导航控制器推送一个新控制器时,前一个控制器的视图会从窗口中移除。它仍然存在于内存中,但已被删除。同样,当您从导航控制器内部呈现模态控制器时,导航控制器的视图将从窗口中删除(但仍在内存中)。别担心;当呈现的东西再次可见时,它会将它们全部放回。
  • 注意,我并不是说它会从窗口中删除所有其他视图。只有它知道的控制器拥有的视图才会被新呈现的东西完全覆盖。
猜你喜欢
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多