View Controller 基本知识(二)
1.视图控制器的分类
图1-5描述了UIKit框架中可用的视图控制器类及其相关的一些重要的其他类。例如,选项栏视图控制器UITabBarController对象管理着一个UITabBar选项栏对象,这个选项对象显示和选项栏接口相关的选项卡,其他框架定义额外的视图控制器类中没有显示在此图中。
图1-5视图控制器,包括iOS提供的和自定义的,都可以被分为两种普通类型——内容视图控制器和容器视图控制器,这反映了视图控制器在app中充当的角色。
1.1 内容视图控制器显示内容
视图控制器使用一个视图或者一组以视图层级结构存在的视图显示内容在屏幕。目前为止讨论的控制器都是内容视图控制器。一个视图控制器通常知晓和其角色相关的部分app数据。
以下是一些需要使用到内容视图控制器的例子:
1)显示数据给用户;
2)收集数据从用户;
3)执行一项指定任务;
4)在一组可用的命令或者选中的导航,例如一个游戏的启动画面。
内容视图控制器是app主要协调对象,因为他们知道数据的具体细节和提供给用户的任务。
我们创建的每个内容视图控制器都负有管理所有的单一视图层级内的视图的责任。视图控制器和视图之间的一一对应的视图层次是设计考虑的关键。我们不应该用多个内容视图控制器管理同一个视图层级。相似的,不能用一个内容视图控制器管理多个屏幕内容。
表格视图控制器
对于有表格显示需求的app,iOS已经内建了一个专门的表格视图控制器来管理表格数据。这个UITableViewController类,管理着表格视图和大多数与表格相关的如选中、行编辑及表格配置的操作支持。这些额外的支持可以让我们用最少的代码快速初始化一个表格出来。并且我们也可以实现自己的表格控制器子类从而可以添加其他的自定义行为。
图1-6是一个使用表格视图控制器的例子。由于表格视图控制器是视图控制器的子类,表格视图控制器仍然有一个指向根视图界面的指针,但其也有一个分开的指向显示在根视图中的表格的指针。
图1-61.2 内容视图控制排列其他视图控制器的内容
一个内容视图控制器包含其他视图控制器拥有的内容。这些视图控制器被显式地分配容器视图控制器作为它们的子内容。一个容器控制器即可以作为父视图也可以作为子内容。最终,这种结构的控制器形成了一个视图控制器层级。
每种类型的容器视图控制器都创建了一个其子视图在内操作的用户界面。这个用户界面的视觉呈现和设计在不同容器视图控制器具有很大的差异性。例如,这里有一些不同容器视图控制器用于区别彼此的方式:
1)容器会提供自己的API去管理子视图;
2)容器决定了子视图之间的关系和关系类型;
3)容器管理着类似视图控制器的视图层级,容器也可以添加子视图控制器的视图到它的视图层级中。容器决定了何时添加视图和如何适配视图层级的视图尺寸,但是在其他情况下子视图控制器仍然负责管理它的视图和子视图。
4)一个容器可能要特别考量设计在它的子内容上。例如,容器可能会限制其子内容对一些视图控制器类,或者它可能期望这些控制器提供额外的内容需要配置容器的视图。
内建的容器类的用户界面已经被组织好了,我们可以通过这些容器类管理的用户界面构建我更复杂的应用。
导航控制器
导航控制器代表被按照等级关系组织的数据,并且它是UINavigationController类的实例。这个类提供的方法支持以堆栈的方式管理内容集合视图控制器。这个堆栈代表用户访问层级数据的路径,堆栈底反应了用户访问的起点,堆栈顶反应了用户当前的位置。
图1-7显示了通讯录中的屏幕,通讯录使用了导航控制器显示通讯录信息给用户。每个界面顶部的导航栏都属于导航控制器,其余的显示给用户的内容受管于内容视图控制器。当用户在界面中和这些控制器做交互,这些控制器告诉导航控制器根据顺序显示下一个视图控制器或者隐藏当前视图控制器。
图1-7虽然一个导航控制器的主要工作是管理它的子视图控制器,但是也管理一些视图。特别的,它管理一个导航栏(显示用户当前位置信息在数据层级中),一个按钮(用户返回之前屏幕),或者其他当前视图控制器需要的自定义控制器。我们不能直接修改视图控制器的视图,相反,我们可以通过设置每个子视图控制器的属性配置导航控制器显示的控制器。
选项栏控制器
使用选项栏控制器可以把app分割成两个或更多个操作区域。选型栏控制器是UITabBarController 的实例。选项栏可以有多个选项卡,每个都相当于一个子视图控制器。选中一个选项卡会使选项栏控制器显示和选项卡相关的视图控制器的内容在屏幕上。
图1-8显示了几个时钟应用的不同模式和它们的视图控制器之间的对应关系。每个模式有一个内容视图控制器管理着主内容区域。在时钟应用这种情况下,时钟和闹钟视图控制器两个都显示一个导航形式的接口以适应一些附加的控制在屏幕顶端。其他模式使用内容视图控制器呈现一个单一的屏幕。
图1-8使用选项栏控制器当我们的app需要呈现不同类型的数据或者用不同的方式呈现相同的数据。
分屏视图控制器
分屏视图控制器将屏幕分割成多个部分,每个都可以独自更新。这种分屏的显示很依赖设备显示的重力方向。分屏视图控制器是UISplitViewController的实例。分屏视图的界面内容来自两个视图控制器。
图1-9显示的是一个分屏的视图界面。竖屏模式下,只显示详情视图,列表视图在弹出窗口中显示。但是,横屏模式下,分屏控制器在两侧都显示各自的内容。
图1-9弹窗控制器
同样在图1-9中,在竖屏模式下,主视图显示在一个弹窗中。在iPad应用中,可以使用弹窗控制器实现弹窗在我们自己的应用中。
弹窗控制器并不是一个容器,它没有继承自UIViewController。但是,在实际应用中,弹窗控制器类似于容器,所以使用它时适用于同样的编程原则。
分页视图控制器
分页视图控制器是用来实现分页布局的视图容器。这种布局允许用户在类似书本的分开的内容页面之间翻动。分页视图控制器是UIPageViewController的实例。内容视图控制器提供内容页。分页视图控制器管理着页面之间的过渡。当需要翻页时,分页视图控制器调用相关的数据获取新页面的视图控制器。
2.视图控制器的内容可以有多种方式显示
显示给用户的视图控制器的内容,必须是和window关联起来的,这里可以有多种实现方式。
1)视图控制器作为根视图控制器;
2)视图控制器作为容器的子内容;
3)在弹出窗中显示视图控制器;
4)从其他视图控制器推出。
图1-10是一个通讯录的例子。当用户单击添加按钮添加一条新的通讯录时,通讯录视图控制器推出了添加通讯录的视图控制器。这个视图控制器一直保持可见直到用户取消操作或者输入了完整的信息后保存通讯内容到数据库。如此,通讯信息被传送到了通讯录视图控制器,刚才的添加通讯录的视图控制器就可以退场了。
图1-10这个被推出的视图控制器并没有指定其类型--既可以是内容视图控制器,也可以是容器视图控制器,都附加了内容视图控制器在其上。在实际中,内容视图控制器被设计成被另一视图控制器推出,因此作为一个变化的内容视图控制器可能是非常有意义的。
很多情况下,我们推出的视图控制器为了达到一些目的去收集用户信息或者吸引用户注意,一旦这些目的达成,当前的被推出视图控制器就要退场,app要返回到标准的用户界面。
被推出的视图控制器本身并不能代表其他的视图控制器。当我们想执行几个独立的模型动作时,链接在一起的视图控制器链是非常有用的。例如,图1-10中用户在添加新通讯录界面中单击添加相片按钮想选择已经存在的相片,这个新通讯录视图控制器就要推出一个选取相片的界面。用户要返回到通讯录列表视图就需要先退出选取相片界面,然后再退出新通讯录界面。
当推出一个视图控制器,就有一个视图控制器决定了其占据屏幕内容的多少,部分屏幕被默认地称为显示上下文环境,显示上下文环境被用来覆盖窗口。