ViewController编程参考
Last updated
Was this helpful?
Last updated
Was this helpful?
视图控制器是应用程序内部结构的基础。每个应用程序至少都有一个视图控制器,大多数应用程序都有多个。每个视图控制器管理应用程序用户界面的一部分以及该界面与基础数据之间的交互。视图控制器还有助于在用户界面的不同部分之间进行转换。
由于它们在您的应用程序中扮演着如此重要的角色,因此视图控制器几乎是您所做的每件事的核心。UIViewController类定义了用于管理视图,处理事件,从一个视图控制器过渡到另一个视图控制器以及与应用程序的其他部分协调的方法和属性。您可以将UIViewController(或其子类别之一)作为子类,并添加实现应用程序行为所需的自定义代码。
有两种类型的视图控制器:
内容视图控制器管理您的应用程序中的离散内容,是您创建的视图控制器的主要类型。
容器视图控制器从其他视图控制器(称为子视图控制器)收集信息,并以有助于导航或以不同方式呈现那些视图控制器的内容的方式来呈现信息。
大多数应用程序是两种类型的视图控制器的混合体。
视图控制器的最重要角色是管理视图层次结构。每个视图控制器都有一个根视图,其中包含了视图控制器的所有内容。在该根视图中,添加显示内容所需的视图。下图说明了视图控制器及其视图之间的内置关系。视图控制器始终对其根视图具有引用,而每个视图对其子视图均具有强引用。
通常,使用outlet来访问视图控制器的视图层次结构中的其他视图。由于视图控制器管理其所有视图的内容,因此outlet可让您存储对所需视图的引用。从情节提要中加载视图时,outlet本身会自动连接到实际视图对象。
内容视图控制器自己管理所有视图。容器视图控制器管理自己的视图以及来自其一个或多个子视图控制器的根视图。容器不管理其子级的内容。它仅管理根视图,并根据容器的设计调整大小和放置它。下图说明了拆分视图控制器及其子级之间的关系。拆分视图控制器管理其子视图的整体大小和位置,但是子视图控制器管理这些视图的实际内容。
视图控制器充当其管理的视图与应用程序数据之间的中介。 UIViewController类的方法和属性使您可以管理应用程序的视觉呈现。当对UIViewController进行子类化时,可以在子类中添加管理数据所需的所有变量。添加自定义变量会创建如下图所示的关系,其中视图控制器具有对您的数据以及用于表示该数据的视图的引用。在这两者之间来回移动数据是您的责任。
您应该始终在视图控制器和数据对象中保持职责的清晰区分。确保数据结构完整性的大多数逻辑都属于数据对象本身。视图控制器可能会验证来自视图的输入,然后以数据对象所需的格式打包这些输入,但是您应尽量减少视图控制器在管理实际数据中的作用。
UIDocument对象是一种与视图控制器分开管理数据的方法。文档对象是一个控制器对象,它知道如何读取数据并将其写入持久性存储。子类化时,您将添加提取数据所需的任何逻辑和方法,并将其传递给视图控制器或应用程序的其他部分。视图控制器可能会存储接收到的所有数据的副本,以便更轻松地更新视图,但是文档仍然拥有真实数据。
视图控制器是响应程序对象,并且能够处理响应程序链中的事件。尽管他们能够这样做,但是视图控制器很少直接处理触摸事件。相反,视图通常会处理自己的触摸事件,并将结果报告给关联的委托或目标对象的方法,该方法通常是视图控制器。因此,视图控制器中的大多数事件都是使用委托方法或动作方法处理的。
视图控制器对其视图及其创建的任何对象承担全部责任。UIViewController类自动处理视图管理的大多数方面。例如,UIKit自动释放不再需要的所有与视图相关的资源。在UIViewController子类中,您负责管理显式创建的任何对象。
当可用的可用内存不足时,UIKit会要求应用释放不再需要的任何资源。实现此目的的一种方法是调用视图控制器的didReceiveMemoryWarning方法。使用该方法删除对不再需要或以后可以轻松重新创建的对象的引用。例如,您可以使用该方法删除缓存的数据。当内存不足时,释放尽可能多的内存非常重要。占用过多内存的应用可能会被系统直接终止以恢复内存。
视图控制器负责其视图的表示并负责调整该表示以匹配基础环境。每个iOS应用程序都应该能够在iPad和几种不同尺寸的iPhone上运行。与其为每个设备提供不同的视图控制器和视图层次结构,不如使用单个视图控制器使它的视图适应不断变化的空间要求,这更加简单。
在iOS中,视图控制器需要处理粗粒度的更改和细粒度的更改。当视图控制器的特征发生变化时,就会发生粗粒度的变化。特性是描述总体环境的属性,例如显示比例。视图控制器的水平和垂直尺寸类别是两个最重要的特征,它们指示了视图控制器在给定维度中的空间。您可以使用大小类更改来更改视图布局的方式,如下图所示。当水平尺寸类别是常规的时,视图控制器将利用额外的水平空间来安排其内容。当水平尺寸类别紧凑时,视图控制器将垂直排列其内容。
在给定的尺寸级别内,可能会随时发生更细粒度的尺寸更改。当用户将iPhone从纵向旋转到横向时,尺寸类别可能不会更改,但屏幕尺寸通常会更改。使用自动版式时,UIKit会自动调整视图的大小和位置以匹配新尺寸。 View Controller可以根据需要进行其他调整。
应用的视图控制器之间的关系定义了每个视图控制器所需的行为。UIKit希望您以规定的方式使用视图控制器。维持正确的视图控制器关系可确保在需要时将自动行为传递给正确的视图控制器。如果您破坏了规定的遏制和演示关系,则应用程序的某些部分将停止按预期运行。
根视图控制器是视图控制器层次结构的基础。每个窗口只有一个根视图控制器,其内容填充该窗口。根视图控制器定义了用户看到的初始内容。下图显示了根视图控制器和窗口之间的关系。由于窗口本身没有可见的内容,因此视图控制器的视图将提供所有内容。
可以从UIWindow对象的rootViewController属性访问根视图控制器。当您使用情节提要板配置视图控制器时,UIKit会在启动时自动设置该属性的值。
容器视图控制器使您可以从更易管理和可重用的部分组装复杂的界面。容器视图控制器将一个或多个子视图控制器的内容与可选的自定义视图混合在一起,以创建其最终接口。例如,UINavigationController对象显示子视图控制器中的内容以及导航栏和可选工具栏,这些内容由导航控制器管理。UIKit包含几个容器视图控制器,包括UINavigationController,UISplitViewController和UIPageViewController。
容器视图控制器的视图始终填充为其分配的空间。容器视图控制器通常作为根视图控制器安装在窗口中(如下图所示),但是它们也可以模态显示或作为其他容器的子代安装。容器负责适当地放置其子视图。在图中,容器将两个子视图并排放置。尽管它取决于容器接口,但是子视图控制器可能对容器和任何同级视图控制器的了解最少。
由于容器视图控制器管理其子控制器,因此UIKit定义了有关如何在自定义容器中设置这些子控制器的规则。
呈现视图控制器会用新视图控制器的内容替换当前视图控制器的内容,通常会隐藏前一个视图控制器的内容。演示文稿最常用于模态显示新内容。例如,您可能会提供一个视图控制器来收集用户的输入。您也可以将它们用作应用界面的常规构建块。
呈现视图控制器时,UIKit会在呈现视图控制器和呈现视图控制器之间创建一个关系,如下图所示。(从呈现的视图控制器回到其呈现的视图控制器,也存在反向关系。)这些关系构成视图控制器层次结构的一部分,是在运行时定位其他视图控制器的一种方式。
当涉及到容器视图控制器时,UIKit可能会修改表示链以简化您必须编写的代码。不同的演示样式对其在屏幕上的显示方式有不同的规则-例如,全屏演示始终覆盖整个屏幕。当您呈现视图控制器时,UIKit会寻找一个为呈现提供合适上下文的视图控制器。在很多情况下,UIKit选择最近的容器视图控制器,但也可能选择窗口的根视图控制器。在某些情况下,您还可以告诉UIKit哪个视图控制器定义了演示上下文并应处理该演示。
下图显示了为什么容器通常为演示提供上下文。当执行全屏演示时,新的视图控制器需要覆盖整个屏幕。容器决定是否处理演示文稿,而不是要求孩子知道其容器的范围。由于示例中的导航控制器覆盖整个屏幕,因此它充当呈现视图控制器并启动呈现。
视图控制器是在iOS上运行的应用程序必不可少的工具,UIKit的视图控制器基础结构使创建复杂的界面变得容易,而无需编写大量代码。在实现自己的视图控制器时,请使用以下提示和准则来确保您未做会干扰系统预期自然行为的事情。
许多iOS框架定义了视图控制器,您可以在应用程序中按原样使用它们。使用这些系统提供的视图控制器可以为您节省时间,并确保为用户提供一致的体验。
大多数系统视图控制器是为特定任务而设计的。一些视图控制器提供对用户数据(例如联系人)的访问。其他人可能会提供对硬件的访问权限,或提供经过特殊调整的接口来管理媒体。例如,UIKit中的UIImagePickerController类显示一个标准接口,用于捕获图片和视频以及访问用户的相机胶卷。
在创建自己的自定义视图控制器之前,请查看现有框架以查看是否已经存在要执行的任务的视图控制器。
UIKit框架提供了用于在iCloud上显示警报,拍摄照片和视频以及管理文件的视图控制器。 UIKit还定义了许多标准的容器视图控制器,可用于组织内容。
GameKit框架提供了视图控制器,用于匹配玩家并管理排行榜,成就和其他游戏功能。
通讯簿UI框架提供了用于显示和选择联系人信息的视图控制器。
MediaPlayer框架提供了用于播放和管理视频以及从用户库中选择媒体资产的视图控制器。
EventKit UI框架提供了用于显示和编辑用户日历数据的视图控制器。
GLKit框架提供了用于管理OpenGL渲染图面的视图控制器。
Multipeer Connectivity框架提供了视图控制器,用于检测其他用户并邀请他们进行连接。
PassKit框架提供了用于显示通行证并将其添加到存折的视图控制器。
社交框架提供了用于为Twitter,Facebook和其他社交媒体网站撰写消息的视图控制器。
AVFoundation框架提供了一个用于显示媒体资产的视图控制器。
切勿修改系统提供的视图控制器的视图层次结构。每个视图控制器拥有其视图层次结构,并负责维护该层次结构的完整性。进行更改可能会在您的代码中引入错误,或者使所属的视图控制器无法正常运行。对于系统视图控制器,始终依靠视图控制器的公共可用方法和属性来进行所有修改。
视图控制器应始终是独立的对象。任何视图控制器都不应该了解其他视图控制器的内部工作原理或视图层次结构。如果两个视图控制器需要来回通信或来回传递数据,则应始终使用显式定义的公共接口来进行通信。
委托设计模式通常用于管理视图控制器之间的通信。通过委托,一个对象定义了用于与关联的委托对象进行通信的协议,该委托对象是符合该协议的任何对象。委托对象的确切类型并不重要。重要的是它实现了协议的方法。
仅将视图控制器的根视图用作其余内容的容器。将根视图用作容器可为所有视图提供一个公共的父视图,这使许多布局操作变得更加简单。许多自动版式约束要求使用公共父视图来正确布置视图。
在模型-视图-控制器设计模式中,视图控制器的作用是促进模型对象与视图对象之间的数据移动。视图控制器可能将一些数据存储在临时变量中并执行一些验证,但是其主要职责是确保其视图包含准确的信息。您的数据对象负责管理实际数据并确保该数据的整体完整性。
UIDocument和UIViewController类之间的关系中存在数据和接口分离的示例。具体来说,两者之间不存在默认关系。 UIDocument对象协调数据的加载和保存,而UIViewController对象协调屏幕上视图的显示。如果在两个对象之间创建关系,请记住,视图控制器应仅缓存文档中的信息以提高效率。实际数据仍然属于文档对象。
应用程序可以在各种iOS设备上运行,并且视图控制器旨在适应这些设备上不同尺寸的屏幕。与其使用单独的视图控制器来管理不同屏幕上的内容,不如使用内置的适应性支持来响应视图控制器中尺寸和尺寸类别的变化。UIKit发送的通知使您可以对用户界面进行大规模和小规模更改,而不必更改其余的视图控制器代码。