上一个章节走了一遍 ViewController 和 TableView 的流程,这章节开始走一遍 Delegate(委托)的流程(不必担心你还不知道委托的概念),涉及到委托,那么在列表里确实有一个例子。
当你轻点单元行的时候,单元行的颜色就变成了灰色来表示你已经选中了这一行,但是当你继续向下滑动的时候,这个单元格依旧保持选中的状态,接下来,你将更改这种通过点击行的方式来转换是否有 CheckMark (对号) 。
点击行是由 Table View 的委托来处理的,在 IOS 中你会经常发现,一个对象会帮另一对象做一些工作,数据源就是一个例子,当然 Table View 还要依赖另一个帮手——委托。
委托的概念在 IOS 中很常见,一个对象会经常依赖另一个对象去帮助它完成某项工作。这种「关注点分离 」(separation of concerns) 的设计可以让系统保持简单,让每个对象只做自己最擅长做的事,其他的对象负责余下的部分。Table View 就是这样的一个例子。
因为每个 APP 都有自己的需求,需要让数据在观感上呈现出什么样子,那么就要求 Table View 有能力处理大量的不同类型的数据。UIKit 的设计者不必担心去制作复杂的 Table View 或者为了自己的 APP 而修改使其适应,而是将填充单元格的任务委托给一个数据源。
Table View 并不关心你要处理的数据源类型,它只是发送一个cellForRowAt 消息,并接受一个用于返回的单元格。这将使 Table View 的组件变得简单,并且将处理数据的责任转移到你的代码中。
同样的,当用户点击行的时候,Table View 也知道如何识别用户行为。但是点击行后执行什么操作则完全取决于APP 了。在这个Checklists 这个 APP 里,你将用这个来实现 CheckMark (对号) 是否标识的转换;在其他的 APP 里则要发挥你的想象力了。
使用委托系统,当点击发生时,可以简单地发送信息并且让委托来排序。
通常使用组件只有一个委托,但是 Table View 将委托分成了两步:首先,UITableViewDateSource 将单元行放进表格中, 然后 UITableViewDelegate 来处理点击行的操作和其他任务。
下面要开始动手执行一些操作了
打开 storyboard 找到 Table View ,然后按住 Ctrl 键并单击它,你将会看到如下情景
表单的数据源和委托都已经和 ViewControll 挂钩了.png你已经看到了 Table View 的 dateSource 和 delegate 都已经和 view Controller 产生了连接。
在Checklist ViewController.swift 中添加如下方法
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
tableView(didSelectRowAt)
是委托方法之一,它的作用是当用户在做任何一次点击单元行操作的时候都会调用这个方法。这时,你可以重新运行你的 APP,你会发现当你点击单元行时,单元行背景只是短暂的变成灰色。
让我们继续修改代码,实现通过点击转换 CheckMark 吧。在刚刚添加的方法上做如下修改。
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) { if cell.accessoryType == .none { cell.accessoryType = .checkmark } else { cell.accessoryType = .none } }
tableView.deselectRow(at: indexPath, animated: true)
}
CheckMark 是单元行的一部分 (属于accessory),首先你需要的就是用 UITableView 的对象来获取一个可以点击操作的单元行对象(即内部变量中的 tableView)。参数中的 indexPath 的作用是防止在被隐藏的单元行下执行点击单元行时需要更加繁复的处理。
当你得到了 UITableView 的对象,你就可以找到这个对象带有的任何 accessoryType 了,当我们检测到该单元行下的 accessoryType 为 none
的时候,就赋值给它checkmark
,相反的我们赋值为none
现在重新运行你的 APP,你将可以通过点击来切换单元格后的 CheckMark 了。
到这里又发现了一个新的问题,当你以非常快的速度向下滑动单元格的时候,以前没有勾选过的单元格可能又被重新勾选了。这是为什么呢?因为这里涉及到两个概念,一个是 cell 和 row。我们修改的是 cell 的 accessory ,但是给 cell 做展示的是 row,而 row 是要被重复利用的,因为你整个屏幕只能展示13行的数据,那其余不可见得行其实是被隐藏掉了,这样可以大大的节约 iPhone的内存并且提高效率,否则很快iPhone 的内存将会被用光。我们回过头来继续说cell 和 row 的事,那么在这样的情况下我们就需要将哪一行是否有对号标记这件事存储一段时间,那么我们就要用到合适的 数据模型。
下一章: 数据模型
网友评论