0%

UIKit 框架_窗口和视图介绍

本文转载自:
http://www.cnblogs.com/CHONGCHONG2008/archive/2012/08/02/2619366.html

窗口和视图

窗口和视图是为 iPhone 应用程序构造用户界面的可视组件。
窗口为内容显示提供背景平台,而视图负责绝大部分的内容描画,并负责响应用户的交互。

什么是窗口和视图?

和 Mac OS X 一样,iPhone OS 通过窗口和视图在屏幕上展现图形内容。虽然窗口和视图对象之间在两个平台上有很多相似性,但是具体到每个平台上,它们的作用都有轻微的差别。

UIWindow 的作用

和 Mac OS X 的应用程序有所不同,iPhone 应用程序通常只有一个窗口,表示为一个 UIWindow 类的实例。您的应用程序在启动时创建这个窗口(或者从 nib 文件进行装载),并往窗口中加入一或多个视图,然后将它显示出来。窗口显示出来之后,您很少需要再次引用它。

在 iPhone OS 中,窗口对象并没有像关闭框或标题栏这样的视觉装饰,用户不能直接对其进行关闭或其它操作。所有对窗口的操作都需要通过其编程接口来实现。应用程序可以借助窗口对象来进行事件传递。窗口对象会持续跟踪当前的第一响应者对象,并在 UIApplication 对象提出请求时将事件传递它。

还有一件可能让有经验的 Mac OS X 开发者觉得奇怪的事是 UIWindow 类的继承关系。在 Mac OS X 中,NSWindow 的父类是 NSResponder;而在 iPhone OS 中,UIWindow 的父类是 UIView。因此,窗口在 iPhone OS 中也是一个视图对象。不管其起源如何,您通常可以将 iPhone OS 上的窗口和 Mac OS X 的窗口同样对待。也就是说,您通常不必直接操作 UIWindow 对象中与视图有关的属性变量。

在创建应用程序窗口时,您应该总是将其初始的边框尺寸设置为整个屏幕的大小。如果您的窗口是从 nib 文件装载得到,Interface Builder 并不允许创建比屏幕尺寸小的窗口;然而,如果您的窗口是通过编程方式创建的,则必须在创建时传入期望的边框矩形。除了屏幕矩形之外,没有理由传入其它边框矩形。屏幕矩形可以通过 UIScreen 对象来取得,具体代码如下所示:

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// 设置根视图控制器
ViewController *viewController = [[ViewController alloc] init];
self.window.rootViewController = viewController;

self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];

虽然 iPhone OS 支持将一个窗口叠放在其它窗口的上方,但是您的应用程序永远不应创建多个窗口。系统自身使用额外的窗口来显示系统状态条、重要的警告、以及位于应用程序窗口上方的其它消息。如果您希望在自己的内容上方显示警告,可以使用 UIKit 提供的警告视图,而不应创建额外的窗口。

UIView 是作用视图

是 UIView 类的实例,负责在屏幕上定义一个矩形区域。在 iPhone 的应用程序中,视图在展示用户界面及响应用户界面交互方面发挥关键作用。每个视图对象都要负责渲染视图矩形区域中的内容,并响应该区域中发生的触碰事件。这一双重行为意味着视图是应用程序与用户交互的重要机制。在一个基于模型 - 视图 - 控制器的应用程序中,视图对象明显属于视图部分。

除了显示内容和处理事件之外,视图还可以用于管理一或多个子视图。子视图是指嵌入到另一视图对象边框内部的视图对象,而被嵌入的视图则被称为父视图或超视图。视图的这种布局方式被称为视图层次,一个视图可以包含任意数量的子视图,通过为子视图添加子视图的方式,视图可以实现任意深度的嵌套。视图在视图层次中的组织方式决定了在屏幕上显示的内容,原因是子视图总是被显示在其父视图的上方;这个组织方法还决定了视图如何响应事件和变化。每个父视图都负责管理其直接的子视图,即根据需要调整它们的位置和尺寸,以及响应它们没有处理的事件。

由于视图对象是应用程序和用户交互的主要途径,所以需要在很多方面发挥作用,下面是其中的一小部分:

1. 描画和动画
    * 视图负责对其所属的矩形区域进行描画。
    * 某些视图属性变量可以以动画的形式过渡到新的值。

2. 布局和子视图管理
    * 视图管理着一个子视图列表。
    * 视图定义了自身相对于其父视图的尺寸调整行为。
    * 必要时,视图可以通过代码调整其子视图的尺寸和位置。
    * 视图可以将其坐标系统下的点转换为其它视图或窗口坐标系统下的点。

3. 事件处理
   *  视图可以接收触摸事件。
   * 视图是响应者链的参与者。

在 iPhone 应用程序中,视图和视图控制器紧密协作,管理若干方面的视图行为。视图控制器的作用是处理视图的装载与卸载、处理由于设备旋转导致的界面旋转,以及和用于构建复杂用户界面的高级导航对象进行交互。

UIKit 的视图类

UIView 类定义了视图的基本行为,但并不定义其视觉表示。相反,UIKit 通过其子类来为像文本框、按键、及工具条这样的标准界面元素定义具体的外观和行为。图 1 显示了所有 UIKit 视图类的层次框图。除了 UIView 和 UIControl 类是例外,这个框图中的大多数视图都设计为可直接使用,或者和委托对象结合使用。

图1 视图的类层次

这个视图层次可以分为如下几个大类:

  1. 容器

    容器视图用于增强其它视图的功能,或者为视图内容提供额外的视觉分隔。比如,UIScrollView 类可以用于显示因内容太大而无法显示在一个屏幕上的视图。UITableView 类是 UIScrollView 类的子类,用于管理数据列表。表格的行可以支持选择,所以通常也用于层次数据的导航 — 比如用于挖掘一组有层次结构的对象。

    UIToolbar 对象则是一个特殊类型的容器,用于为一或多个类似于按键的项提供视觉分组。工具条通常出现在屏幕的底部。Safari、Mail、和 Photos 程序都使用工具条来显示一些按键,这些按键代表经常使用的命令。工具条可以一直显示,也可以根据应用程序的需要进行显示。

  2. 控件

    控件用于创建大多数应用程序的用户界面。控件是一种特殊类型的视图,继承自 UIControl 超类,通常用于显示一个具体的值,并处理修改这个值所需要的所有用户交互。控件通常使用标准的系统范式(比如目标 - 动作模式和委托模式)来通知应用程序发生了用户交互。控件包括按键、文本框、滑块、和切换开关。

  3. 显示视图

    控件和很多其它类型的视图都提供了交互行为,而另外一些视图则只是用于简单地显示信息。具有这种行为的 UIKit 类包括 UIImageView、 UILabel、UIProgressView、UIActivityIndicatorView

  4. 文本和 web 视图

    文本和 web 视图为应用程序提供更为高级的显示多行文本的方法。UITextView 类支持在滚动区域内显示和编辑多行文本;而 UIWebView 类则提供了显示 HTML 内容的方法,通过这个类,您可以将图形和高级的文本格式选项集成到应用程序中,并以定制的方式对内容进行布局。

  5. 警告视图和动作表单

    警告视图和动作表单用于即刻取得用户的注意。它们向用户显示一条消息,同时还有一或多个可选的按键,用户通过这些按键来响应消息。警告视图和动作表单的功能类似,但是外观和行为不同。举例来说, UIAlertView 类在屏幕上弹出一个蓝色的警告框,而 UIActionSheet 类则从屏幕的底部滑出动作框。

  6. 导航视图

    页签条和导航条和视图控制器结合使用,为用户提供从一个屏幕到另一个屏幕的导航工具。在使用时,您通常不必直接创建 UITabBarUINavigationBar 的项,而是通过恰当的控制器接口或 Interface Builder 来对其进行配置。

  7. 窗口

    窗口提供一个描画内容的表面,是所有其它视图的根容器。每个应用程序通常都只有一个窗口。

除了视图之外, UIKit 还提供了视图控制器,用于管理这些对象。更多信息请参见 “视图控制器的作用” 部分。

视图控制器的作用

运行在 iPhone OS 上的应用程序在如何组织内容和如何将内容呈现给用户方面有很多选择。含有很多内容的应用程序可以将内容分为多个屏幕。在运行时,每个屏幕的背后都是一组视图对象,负责显示该屏幕的数据。一个屏幕的视图后面是一个视图控制器其作用是管理那些视图上显示的数据,并协调它们和应用程序其它部分的关系。

UIViewController 类负责创建其管理的视图及在低内存时将它们从内容中移出。视图控制器还为某些标准的系统行为提供自动响应。比如,在响应设备方向变化时,如果应用程序支持该方向,视图控制器可以对其管理的视图进行尺寸调整,使其适应新的方向。您也可以通过视图控制器来将新的视图以模式框的方式显示在当前视图的上方。

除了基础的 UIViewController 类之外,UIKit 还包含很多高级子类,用于处理平台共有的某些高级接口。特别需要提到的是,导航控制器用于显示多屏具有一定层次结构的内容;而页签条控制器则支持用户在一组不同的屏幕之间切换,每个屏幕都代表应用程序的一种不同的操作模式。

有关如何通过视图控制器管理用户界面上视图的更多信息,请参见 iPhone OS 的视图控制器编程指南。

视图架构和几何属性

由于视图是 iPhone 应用程序的焦点对象,所以对视图与系统其它部分的交互机制有所了解是很重要的。UIKit 中的标准视图类为应用程序免费提供相当数量的行为,还提供了一些定义良好的集成点,您可以通过这些集成点来对标准行为进行定制,完成应用程序需要做的工作。

本文的下面部分将解释视图的标准行为,并说明哪些地方可以集成您的定制代码。如果需要特定类的集成点信息,请参见该类的参考文档。您可以从 UIKit 框架参考中取得所有类参考文档的列表。

视图交互模型

任何时候,当用户和您的程序界面进行交互、或者您的代码以编程的方式进行某些修改时,UIKit 内部都会发生一个复杂的事件序列。在事件序列的一些特定的点上,UIKit 会调用您的视图类,使它们有机会代表应用程序进行事件响应。理解这些调用点是很重要的,有助于理解您的视图对象和系统在哪里进行结合。图 2 显示了从用户触击屏幕到图形系统更新屏幕内容这一过程的基本事件序列。以编程方式触发事件的基本步骤与此相同,只是没有最初的用户交互。
UIKit interactions with your view objects
图2 UIKit和您的视图对象之间的交互

下面的步骤说明进一步刨析了图 2 中的事件序列,解释了序列的每个阶段都发生了什么,以及应用程序可能如何进行响应。

  1. 用户触击屏幕。

  2. 硬件将触击事件报告给 UIKit 框架。

  3. UIKit 框架将触击信息封装为一个 UIEvent 对象,并派发给恰当的视图(有关 UIKit 如何将事件递送给您的视图的详细解释,请参见 “事件的传递” 部分)。

  4. 视图的事件处理方法可以通过下面的方式来响应事件:

    • 调整视图或其子视图的属性变量(边框、边界、透明度等)。
    • 将视图(或其子视图)标识为需要修改布局。
    • 将视图(或其子视图)标识为布局需要重画。
    • 将数据发生的变化通报给控制器。
  5. 当然,上述的哪些事情需要做及调用什么方法来完成是由视图来决定的。
    如果视图被标识为需要重新布局,UIKit 就调用视图的 layoutSubviews: 方法。

    您可以在自己的定制视图中重载这个方法,以便调整子视图的尺寸和位置。举例来说,如果一个视图具有很大的滚动区域,就需要使用几个子视图来 “平铺”,而不是创建一个内存很可能装不下的大视图。在这个方法的实现中,视图可以隐藏所有不需显示在屏幕上的子视图,或者在重新定位之后将它们用于显示新的内容。作为这个过程的一部分,视图也可以将用于 “平铺” 的子视图标识为需要重画。

  6. 如果视图的任何部分被标识为需要重画,UIKit 就调用该视图的 drawRect: 方法。

    UIKit 只对那些需要重画的视图调用这个方法。在这个方法的实现中,所有视图都应该尽可能快地重画指定的区域,且都应该只重画自己的内容,不应该描画子视图的内容。在这个调用点上,视图不应该尝试进一步改变其属性或布局。

    所有更新过的视图都和其它可视内容进行合成,然后发送给图形硬件进行显示。

  7. 图形硬件将渲染完成的内容转移到屏幕。

请注意:上述的更新模型主要适用于采纳内置视图和描画技术的应用程序。如果您的应用程序使用 OpenGL ES 来描画内容,则通常要配置一个全屏的视图,然后直接在 OpenGL 的图形上下文中进行描画。您的视图仍然需要处理触碰事件,但不需要对子视图进行布局或者实现 drawRect: 方法。有关 OpenGL ES 的更多信息,请参见 “用 OpenGL ES 进行描画” 部分。

基于上述的步骤说明可以看出,UIKit 为您自己定制的视图提供如下主要的结合点:

下面这些事件处理方法:

    touchesBegan:withEvent:

    touchesMoved:withEvent:

    touchesEnded:withEvent:

    touchesCancelled:withEvent:

layoutSubviews方法

drawRect:方法

大多数定制视图通过实现这些方法来得到自己期望的行为。您可能不需要重载所有方法,举例来说,如果您实现的视图是固定尺寸的,则可能不需要重载 layoutSubviews 方法。类似地,如果您实现的视图只是显示简单的内容,比如文本或图像,则通常可以通过简单地嵌入 UIImageViewUILabel 对象作为子视图来避免描画。

重要的是要记住,这些是主要的结合点,但不是全部。UIView 类中有几个方法的设计目的就是让子类重载的。您可以通过查阅 UIView 类参考中的描述来了解哪些方法可以被重载。

视图渲染架构

虽然您通过视图来表示屏幕上的内容,但是 UIView 类自身的很多基础行为却严重依赖于另一个对象。UIKit 中每个视图对象的背后都有一个 Core Animation 层对象,它是一个 CALayer 类的实例,该类为视图内容的布局和渲染、以及合成和动画提供基础性的支持。

Mac OS X(在这个平台上 Core Animation 支持是可选的)不同的是,iPhone OSCore Animation 集成到视图渲染实现的核心。虽然 Core Animation 发挥核心作用,但是 UIKitCore Animation 上面提供一个透明的接口层,使编程体验更为流畅。这个透明的接口使开发者在大多数情况下不必直接访问 Core Animation 的层,而是通过 UIView 的方法和属性声明取得类似的行为。然而,当 UIView 类没有提供您需要的接口时,Core Animation 就变得重要了,在那种情况下,您可以深入到 Core Animation 层,在应用程序中实现一些复杂的渲染。

欢迎关注我的其它发布渠道