上一话讲完了小人脸Demo,我们也了解了MVC,那么这一话我们来把Demo复杂化,看看多个MVC之间是如何协同工作的。回顾一下我们之前讲过的多个MVC的情况。
IOS提供了一些控制器,它们的视图是其他MVC。这些控制器包括UITabBarController(选项卡控制器)、UISplitViewController(分栏控制器)、UINavigationController(导航栏控制器).
下面是一个选项卡控制器的示例:
用户点击屏幕下方的按钮选择不同的界面,下面按钮是UITabBarItem类型的,通常你在storyboard中设置它们。如果选项卡按钮多于5个,那么在尾部会以“。。。”来表示,点击可以看到多出来的按钮。
下面是分栏控制器的示例:
分为左右两个MVC。左侧为Master,右侧为Detail.。注意这个视图在iphone和ipad中显示不同,后面会看到。
下面是导航控制器的示例:
导航控制器不像刚才我们介绍的前两个,你可以明显看出多个MVC的排列方式,选项卡使用底部的按钮来指导用户切换MVC,而分栏控制器把两个MVC并排放置。在导航控制器中,我们把MVC看成卡片,那么控制器像放置一堆卡片这样放置MVC,你只能看到最上面的那个MVC,这就是导航控制器在多个MVC之间共享一个小的屏幕空间的方法。
需要注意的是由导航控制器参与绘图的是顶部的一块区域,导航控制器可以在这里设置标题,也可以放一些按钮,但是这部分的具体内容却是由最顶层的MVC决定的,每个顶部MVC通过它的UIViewController里面一个叫做navigationItem的属性来传递顶部的内容给负责控制它的导航控制器。所以我们经常看到随着顶部MVC的变化,页面顶部的内容也在不断变化。底下的部分是由顶部的MVC来绘制的。
点击顶部的General按钮,会把新的MVC放到顶部。
现在我就看不到其他的MVC了,导航控制器也可以在底部绘制几个新的按钮通过顶部MVC控制器中的toolbarItems属性,它由一些列的barItem属性构成。所以与顶部一样,底部的按钮也会随着当前最顶部MVC的不同而不同。
你可以看到最顶部的返回按钮,这个按钮的作用是移走当前最顶部的MVC,我将回到我之前的位置。当点击返回按钮的时候,顶部MVC的移除是完全移除,从堆栈中完全移除了。
我们继续点击
MVC堆中的MVC会越来越多,然后全部点击左上角的返回按钮,直到最后一个MVC,这时候左上角已经没有返回按钮了:
这三个控制器的作用都是展示多重MVC,现在来重点讨论一下导航控制器的工作原理:
顶部紫色的代表一个MVC,我们想在屏幕上增加些功能,但是空间不够了,或者从逻辑上来说我们要添加的东西不应该显示在这个MVC上。所以我们应该创建另外一个MVC来管理那些不属于这个MVC的功能。
所以我应该找到一种方法让这两个MVC能共享一个屏幕控件,我能使用一个分栏控制器或者如果这两者之间是平等关系的话我们可以使用选项卡控制器。当然我们可以使用导航控制器。
导航控制器本身也是一个MVC,一个MVC的控制器,但是它是一个特殊的MVC,它有一个叫做rootViewController的outlet,这个outlet指向某个MVC,确切的说是指向某个MVC的控制器。当这个outlet指向某个MVC的控制器时,就会向那个MVC的视图绘制出来,也就是view属性,我们已经知道控制器的view属性也就是其控制的所有属性的根视图。如下图:
导航控制器把这个view放置到屏幕上,标题栏之下。因为它会布满整个矩形空间,所以标题栏会变成半透明以显示标题栏下面的那部分内容。那么我们如何让其他MVC与我们的导航控制器联系起来呢。当某个在这个视图中的UI元素,例如一个按钮或者其他东西被按下的时候,这可能导致其他的MVC被创建,当我们做这些变换的时候,我们始终会创建新的MVC.
然后导航控制器就会移到新建的MVC上。
然后新的MVC的左上角会有一个返回按钮。
当我们点击这个按钮的时候会返回到第一个MVC中,注意这个时候刚才的MVC已经彻底消失了!它不是被隐藏了,它从内存空间中被deallocated了。
这就是导航控制器的工作原理,分栏控制器和选项卡控制器也是类似的。