导航控制器:窗口上导航控制器中最上面的视图控制器下方是啥?

Posted

技术标签:

【中文标题】导航控制器:窗口上导航控制器中最上面的视图控制器下方是啥?【英文标题】:Navigation Controller : What is below the topmost view controller in navigation controller on the window?导航控制器:窗口上导航控制器中最上面的视图控制器下方是什么? 【发布时间】:2015-05-08 06:24:08 【问题描述】:

窗口导航控制器中最顶层视图控制器下方是什么? (是导航堆栈中的“导航控制器”还是“顶部视图控制器下方的视图控制器”?)

手机窗口上的所有视图控制器是否同时在导航控制器上一个在另一个之下,或者堆栈维护对它们的引用并在调用推送和弹出操作时加载和卸载它们?

【问题讨论】:

【参考方案1】:

您试图将 View 的理解与 ViewController 混为一谈,这有时我们不会注意。

手机窗口上的所有视图控制器是否同时一个在另一个下方

从渲染的角度来看,Window 在其之上托管视图,而不是视图控制器。因此,当通过推送/弹出生成导航堆栈时,窗口会承载导航控制器的视图,这是它的根控制器对象。

导航控制器对象本身由一个UINavigationBar 和一个content view 组成,其中托管子控制器的视图。

现在问题来了,如何维护视图和视图控制器的层次结构。 UINavigationController 一次托管一个视图,因此即使堆栈上有多个控制器,也只会在视图层次结构中加载最顶层控制器的视图。所以视图堆栈类似于

window->navigationControllerView->topMostControllerView

对于视图控制器的层次结构,它们在堆栈上维护并保持活动状态,除非向导航控制器发送弹出消息。有时它们会在收到内存警告时被销毁。其他详情请参考Documentation

为了说明这一点,我生成了一个简单的堆栈跟踪。如果您查看对象 0x7a6cfd60,这是最顶层控制器 MyDocumentsVC 的视图(查看底线),并作为 UIViewControllerWrapperView 的单个子视图呈现,这不过是导航控制器的内容视图。

(lldb) po [[self.navigationController view] subviews]
<__NSArrayM 0x7bad3bf0>(
<UINavigationTransitionView: 0x7bad3a10; frame = (0 0; 768 1024); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7bad3bc0>>,
<UINavigationBar: 0x7b960780; frame = (0 20; 768 44); opaque = NO; autoresize = W; gestureRecognizers = <NSArray: 0x7a69ec40>; layer = <CALayer: 0x7b960300>>
)


(lldb) po [[[[self.navigationController view] subviews] objectAtIndex:0] subviews]
<__NSArrayM 0x7baf59f0>(
<UIViewControllerWrapperView: 0x7a6c2290; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x7a6c2360>>
)


(lldb) po [[[[[[self.navigationController view] subviews] objectAtIndex:0] subviews] objectAtIndex:0] subviews]
<__NSArrayM 0x7a6ec3f0>(
<UIView: 0x7a6cfd60; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x7a6cfdd0>>
)


(lldb) po [self.navigationController viewControllers]
<__NSArrayI 0x7a6e9c20>(
<ViewController: 0x7b956820>,
<MyDocumentsVC: 0x7b96bc30>
)


(lldb) po [[[self.navigationController viewControllers] objectAtIndex:0] view]
<UIView: 0x7a6b68c0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x7a6b6930>>

(lldb) po [[[self.navigationController viewControllers] objectAtIndex:1] view]
<UIView: 0x7a6cfd60; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x7a6cfdd0>>

【讨论】:

非常感谢 :) 很好的解释完全消除了我的疑虑。【参考方案2】:

您的问题似乎令人困惑,但据我了解,应用层次结构是这样描述的

【讨论】:

【参考方案3】:

UINavigationController 堆栈上除了最顶层视图控制器之外的其他视图控制器的视图只要需要就存在,并且可以在收到内存警告时销毁(如果它们没有强引用,这是非常罕见的并且需要一些特殊情况)。

【讨论】:

以上是关于导航控制器:窗口上导航控制器中最上面的视图控制器下方是啥?的主要内容,如果未能解决你的问题,请参考以下文章

交替使用拆分视图控制器和导航控制器作为窗口根视图控制器

以编程方式从嵌入导航控制器的视图中解除弹出窗口

更改根视图控制器不会释放同一窗口上的先前视图控制器

没有“返回”按钮的导航控制器

使用导航呈现自定义大小的视图控制器

在标签栏控制器中访问多个导航控制器