如果 你 花了 大量的时间 使用 iphone 或者 ipad这样的iOS设备,那么 你 肯定 和 UIKit框架中的列表视图 产生过 大量的互动。列表视图 在许多iOS应用程序当中 是 导航系统的基石。比如 iphone的邮件应用程序 和 系统设定应用程序 都 大量 使用了 列表视图 将 信息 用 列表的形式 呈现 给用户。用户 可以点选 列表中的某个特定的项目 来获取 更加详细的信息。
虽然 在绝大多数使用列表视图的情况中 都使用了 导航控制器、导航栏,我们 在这一篇博文中 仅仅 关注 列表视图本身。这样 我们 才能够 更好地 理解 列表视图 是如何 工作的 以及 创建 基于导航控制器的列表视图应用程序。
大致 了解一下 列表视图
在UIKit框架当中 列表视图 属于 UITableView类型的物件。列表视图 会以列表的形式 将 数据 呈现给 用户。在列表视图当中 数据 是 一排一排地 展现出来的。列表视图中的每一排 都是 一个单元格。而 每个单元格 都是 UITableViewCell类型的物件。每个单元格 可以包含 一个物件textLabel 代表 文本标签、一个物件detailedTextLabel 代表 副标题 和 一个物件image 用来代表 图片视图。我们 可以 在单元格上 添加 子视图 或者 创建 一类属于UITableViewCell类型的物件 来实现 更加复杂的单元格。
列表视图代理 和 数据源
每个列表视图 都需要 一个列表视图代理 和 数据源。列表视图所在的视图控制器 只要遵循 UITableViewDataSource这项协议 就可以充当 列表视图的数据源。视图控制器 通过实施UITableViewDataSource这项协议中的措施 可以确定 列表视图 需要显示 多少行数据,需要显示的数据 分为 多少组 以及 提供 需要显示出来的各个单元格。视图控制器 通过实施 UITableViewDelegate这项协议中的措施 可以对 列表视图的外观 和 功能 进行 进一步的控制,比如 探测 用户 点击了 某个特定的单元格 等等。
列表视图风格
列表视图 可以使用 普通风格 也可以使用 分组风格。在分组风格中 单元格 会被组织 在一个用圆角矩形所代表的区域当中,下面的图片 就展示了 分组风格的列表视图 是 什么样子:
在普通风格的列表视图中 所有的项目 都不加分隔地 列举出来,并且 使用 屏幕的全部宽度,就像 这样:
普通风格的列表视图 也可以添加 索引,这样 单元格 可以根据一定的条件 组织起来。
列表视图单元格风格
我们 除了 可以改变 列表视图的风格 还可以改变 列表视图单元格的风格。目前 iOS5 支持 四种不同的单元格风格:
- UITableViewCellStyleDefault-只有 黑色的主标签 向左 对齐。
- UITableViewCellStyleSubtitle-有 黑色的主标签 向左 对齐,在主标签下方 有 小字体的灰色副标签。
- UITableViewCellStyleValue1-有 黑色的主标签 向左 对齐,在同一行中 有 小字体的蓝色副标签 向右 对齐。
- UITableViewCellStyleValue2-在单元格左侧 有 蓝色的主标签 向右 对齐,在单元格右侧 有 黑色的副标签 向左 对齐。
单元格的风格 是 在单元格物件 创建时 确定的,稍后 我们 会详细 了解的。
创建 项目
根据这篇博文的目的 我们 要创建 一个包含列表视图的应用程序。
首先 启动 Xcode 并且 选择 ”Create a new Xcode project”(创建 一个新的Xcode项目)选项。接着 选择 Single View Application(单一视图应用程序)模板后 点击 Next(下一步)。然后 将 Device Family(设备家族)选项 设定为 iPhone 并且 将 产品名称 和 物件类型名称前缀 设定为 TableExample。最后 取消 对Use Storyboard 和 unit test两个选项的勾选 并且 点击 下一步 将 这个项目的所有文件 存储 在你认为合适的地方。
添加 列表视图
我们创建的应用程序 需要 一个列表视图物件,这点 并不 奇怪。我们 点选 TableExampleViewController.xib这个文件,将 其 载入 界面创建器。然后 从物件库中 将 一个列表视图 拖、放 在画布中的视图上,就像 这样:
连接 列表视图代理、数据源 和 视图控制器
为了简单起见,我们 将 TableExampleViewController类型的物件 用作 列表视图的代理 和 数据源。于是 我们 必须对TableExampleViewController类型的物件 实施 UITableViewDataSource 和 UITableViewDelegate这两项协议中规定的措施。在此之前 我们 需要将 列表视图所包含的代理物件delegate 和 数据源物件dataSource 与 视图控制器,也就是 TableExampleViewController类型的物件,连接起来。我们 先要点选 TableExampleViewController.xib这个文件,将 其 载入 界面创建器。然后 点选 视图中的列表视图后 打开 连接查看器(View->Utilities->Show Connections Inspector)。
在连接查看器当中 我们 可以看到 这个:
鼠标 点击 dataSource一栏右侧的圆圈 不放,拖、放 到 File’s Owner图标上:
然后 重复 同样的步骤,将 delegate 和 File’s Owner图标 连接起来。
实现 列表视图的数据源
为了 使 我们的列表视图 工作起来,我们 需要编写 两项措施 并且 使 之 适用于 TableExampleViewController类型的物件。在这之前 我们 需要让 TableExampleViewController类型的物件自己 创建 数据。在这里这个例子当中 我们 创建 一个NSArray类型的数组物件,再 将 一些字符串物件 添加 到这个数组物件当中。我们 先点选 TableExampleViewController.h这个文件,然后 将 其 修改成 这样:
其中的
接下来 我们 需要在载入 TableExampleViewController类型物件所包含的视图时 将 需要显示的数据 存入 TableExampleViewController类型的物件所包含的colors当中。加载 视图控制器中的视图物件时,会对这个视图控制器物件 采取 viewDidLoad这项措施。于是 我们 点选 TableExampleViewController.m这个文件,并且 找到 viewDidLoad这项措施 将 其 修改为 下面这样:
在viewDidLoad这项措施中 我们 为TableExampleViewController类型物件所包含的colors这个物件 分配了 内存空间,并且 将 几种颜色的名称 存储 在colors这个物件当中。
在加载 视图控制器中的视图时,我们 为colors这个数组物件 分配了 内存地址,那么 在卸载 视图控制器中的视图时 就要将 colors这个数组物件所占用的内存空间 腾空。卸载 视图控制器中的视图时,会对这个视图控制器 采取 viewDidUnload这项措施。于是 我们 点选 TableExampleViewController.m这个文件,并且 找到 viewDidUnload这项措施 将 其 修改成 下面这个样子:
我们 已经确定了 TableExampleViewController类型的物件 遵循 UITableViewDataSource这项协议,于是 我们 必须编写出 这项协议中规定的措施 并 使 之 适用于 TableExampleViewController这类物件。UITableViewDataSource这项协议 规定 我们 至少要 编写 numberOfRowsInSection 和 cellForRowAtIndexPath这两项措施。所以 我们 打开 TableExampleViewController.m这个文件,并且 在@implementation命令 和 @end命令之间 加入 numberOfRowsInSection这项措施:
numberOfRowsInSection这项措施的第二个参数section 代表 列表视图中各组单元格的编号,而 numberOfRowsInSection这项措施的作用 就是 计算出 第section组单元格中 包含 多少个单元格。如果 我们的列表视图中 只有 一组单元格,那么 section这个参数 我们 可以置之不理。
这行语句 计算出 colors这个数组物件 包含 多少个元素,并且 将 这个数值 作为结果 传递回去,以便生成 相应数量的单元格。
下一步 我们 在同样这个文件中 加入 cellForRowAtIndexPath这项措施,就像 这样:
cellForRowAtIndex这项措施 附带了 两个参数,第一个参数tableView 代表 表格视图;第二个参数 indexPath 代表 索引路径,这项措施产生的结果 是 表格视图tableView所需要的单元格。首先
这行语句 创建了 一个字符物件CellIdentifier,并且 将 这个字符串物件的内容 设定为 ”Cell”。CellIdentifier这个字符串物件 将用作 单元格复用表识。
这行语句 对 列表视图tableView 采取了 dequeueReusableCellWithIdentifier这项措施,并且 将 单元格复用表识CellIdentifier 用作 参数,从而 从列表视图tableView当中 找出 可以复用的单元格,并 将 地址 存储 在变量cell当中。
接下来
这行语句 检查 是否 没有找到 可以复用的单元格,如果 没有找到 可以复用的单元格,那么 就执行 紧接着的
这行语句,采取 initWithStyle:reuseIdentifier:这项措施 创建 一个全新的单元格。initWithStyle:reuseIdentifier:这项措施的第一个参数UITableViewCellStyleDefault 将 新创建的单元格 设定为 默认风格;第二个参数CellIdentifier 将 新创建的单元格的复用表识 设定为 ”Cell”。
接下来的
这行语句当中 对 当前的索引路径indexPath 采取了 row这项措施,从而 获知 当前需要生成第几个单元格。当前需要生成 第几个单元格,objectAtIndex:这项措施 就会从colors这个数组物件中 找出 第几个颜色名称。最后 将 当前生成的单元格的标签之文本 设定为 刚刚找到的颜色名称。
最后
这行语句 将 我们准备好的单元格 作为结果 传递回去。
编译 运行 程序
这个程序 一旦 编译成功,运行的效果 就应该是 这个样子:
给 表格视图单元格 添加 图片 以及 改变 单元格风格
现在 我们 已经创建了 一个简单的列表视图例子。接下来 我们 看看 如何编写 代码 来改变 单元格的风格。首先 我们 考虑一下 如何 在单元格中 添加 图片。
第一步,我们 需要将 图片文件 添加 到我们的项目当中。比如 现在 我 有 一个图片文件apple.png。我们 在Finder中 找到这个文件,然后 将 其 拖、放 到 Xcode窗口左侧面板中的Supporting Files分组里:
第二步,我们 打开 TableExampleViewController.m这个文件,并且 找到 cellForRowAtIndexPath这项措施。然后 在
这行语句之前 添加 这样两行语句:
其中 第一行语句 用 图片文件apple.png的内容 创建了 一个UIImage类型的图片物件cellImage。第二行语句 将 当前正在准备的单元格cell中 图片视图imageView里的图片image 设定为 图片物件cellImage。
接下来 我们 要给 各个单元格 添加 副标签。每个单元格物件 都包含了 名为detailTextLabel的标签物件,我们 只要设定 这个标签物件的文本 就可以给 单元格 添加 副标签。同样 还是 在cellForRowAtIndexPath这项措施当中,我们 将
这两行语句。其中 第一行语句 创建了 一个字符串物件subtitle,其内容 是 “更多关于某某颜色的内容”。第二行语句 将 我们正在准备的单元格cell中 标签detailTextLabel的文本text 设定为 刚刚创建好的字符串。
最后 编译、运行 这个程序,我们 可以看到 这样的效果: