跳转控制器 push 和 modal 的区别

跳转控制器 push 和 modal 的区别_第1张图片
stack.jpg

写这篇的起因是这样的,朋友小朱写了个控制器 modal 出来,里面用到了 NSTimer 然后他想 dealloc 的时候关闭 timer(由关闭通知监听想到) ,可是就发现该控制器 dissmiss 的时候代码根本不走这里,出现了内存泄露。我建议他在viewWillDisappear之前需要把 NSTimer 销毁了就可以了。再检查下有没有使用 Block 引用实例变量即可解决。可是这让我想到了个问题,控制器跳转的两种方式的区别,好像并不能一下说的很清楚。

所以,首先我来谈谈 push 的管理方式。

NavigationController

  1. 一种最常见的情况 A 控制器上有个按钮 push 到 B 控制器 它上又有个按钮 push C 控制器 这里的内部机制是这样的:
    1.1 每个 NavigationController 都会对应一个 栈 来管理其子控制器,每 push 一个进来就压栈(先进后出),放到栈顶。如下图所示:
    跳转控制器 push 和 modal 的区别_第2张图片
    NavigationControllers.png

    1.2 一旦有控制器进栈,可以简单的理解为:就把这个控制器所对应的 View 创建出来,放到 NavigationController's View 上,若不是栈顶控制器的话,则把之前 NavigationController's View 移除(注意并没有销毁),再添加。如下图所示:
    跳转控制器 push 和 modal 的区别_第3张图片
    PushViewController.png

    现在就可以得出一个结论:
    结论一:显示在导航栏控制器的 View 永远是栈顶控制器的 View。
    1.3 我们再来看从 C控制器 返回到 A控制器,每返回一个就出栈一个,然后把其控制器销毁。如下图所示:
    跳转控制器 push 和 modal 的区别_第4张图片
    popViewController.png

    从上面一系列的分析来看,则可以发现,一个导航控制器对应一个导航条,即多个子控制器共用一个导航条。
    结论二:导航控控制条的内容由栈顶控制器决定(navigationItem)

Modal

2.为了搞清楚 Modal 的原理,我觉得自己撸一个就差不多了。这里给一个我做的过程:
2.1 把控制器的 View 加到 window 上;
2.2 使用 transform 向下平移一个屏幕高度,再清空 transform 完成动画。


跳转控制器 push 和 modal 的区别_第5张图片
CustomModal.png

2.3 由于控制器的创建都是在函数内部完成的,所以函数执行完毕后就内存就回收了。所以如果该控制器还有操作的话,就会 EXC_BAD_ACCESS 所以我要添加一个属性来强引用 ModalVC。
所以就发现 Modal 出的控制器是需要被强引用的,通过看文档也可以发现 Modal 出的控制器会被当前控制器的 presentViewController 保存(强引用)。

你可能感兴趣的:(跳转控制器 push 和 modal 的区别)