一个最简单的UITableView项目
项目基本设置
Xcode并没有提供直接使用UITableView的项目模板,不过我们可以基于一个"Single View Application"手工打造一个。
新建一个叫做UITableViewDemo的"Single View Application",然后,按照下图的设置,我们禁用横屏模式:
"对于一个iPhone app来说,通常,我们也不会选择Upside down,因为来电的时候,Mic和听筒的位置是反的,这很容易给用户带来一些麻烦。"
特别提示
置换新的ViewController
打开Main.storyboard,选中场景中的"View Controller",然后删掉它(因为我们要换一个新的UITableView Controller进来):
然后,打开ViewController.swift,把ViewController改成EpisodeListViewController,并且,让它从UITableViewController继承:
class EpisodeListViewController: UITableViewController { }
然后,在项目列表里,我们把ViewController.swift文件名,修改为EpisodeListViewController.swift:
然后,返回Main.storyboard,在"Object library"里,拖一个UITableViewController进来:
在Identity inspector里,我们把class设置为:EpisodeListViewController:
这样,我们拖进来的UITableViewController就和EpisodeListViewController"关联"起来了。
"为Controller设置Custom class很重要,很多时候我们的代码不好用都是因为我们忘记了设置它。"
特别提示
最后,在"Attribute inspector"里,我们把新添加的UITableViewController设置为"Initial View Controller"。这时UITableViewController左边会出现一个大箭头:
这样,我们的UITableView就会做为默认的View被加载了。按Command + R,我们就能在模拟器里,看到一个空的UITableView了。
Table row Vs Table cell
接下来,在我们向UITableView中添加内容之前,我们要区分两个概念。实际上,我们的Table可能会包含很多内容,每一条记录都可以认为是Table中的一行。但实际上,iPhone的一屏只能显示有限的内容,我们无须为不需要显示的内容分配UI资源。于是,对于UITableView来说,屏幕上的每一行,我们用一个UITableViewCell对象表示。最终,我们用一组有限的UITableViewCell对象,显示了所有需要显示的内容。
实际上,当我们拖拽一个UITableView到Storyboard的时候,Xcode就已经为我们准备了一个UITableViewCell的原型了:
为了自定义这个Cell,我们可以在"Document outline"中选中它:
"当然,你也可以在Storyboard中选中它,但是,要确保你选中的是Cell而不是Table View。"
特别提示
然后,拖拽一个UILabel进来:
我们让它占满整个UITableViewCell,Xcode会给我们对齐的提示:
然后,重新选中"Table View Cell"(确保不要选中UILabel也不要选中Table View),在"Attribute inspector"中,把Accessory设置成"Disclosure indicator",这样Cell的右侧就会出现一个小箭头,表示点击后会切换到新界面:
接下来,我们要给这个Cell起一个"别名",它很重要。当我们需要在一个Table View里显示多种不同类型的Cell时,我们可以用这个"别名"来创建不同的Cell对象。选中Table View Cell,在"Attribute inspector"中,我们把identifier设置成:"EpisodeItem":
这样,一个UITableViewCell对象的基本设置就完成了。简单来说,可以总结成三个部分:
- 定制Cell UI;
- 设置Accessory;
- 设置Identifier;
之后,按Command + R重新编译和执行,结果还是一个空空如也的UITableView,这很正常,因为我们只是定义了一个Cell的"原型",而并没有添加实质的内容。在上一段视频的模拟中,对于:UITableView要显示多少行内容?,每一行都包含什么内容?这样的问题,UITableViewController统统把它"外包"给了它的delegate。我们只要实现对应的protocol方法就可以了。
UITableView Delegate
回到EpisodeListViewController.swift,按住Command点击UITableViewController,在它的定义里,我们可以看到下面的代码:
@available(iOS 2.0, *)
public class UITableViewController : UIViewController,
UITableViewDelegate, UITableViewDataSource { }
它遵从了两个protocol,UITableViewDataSource和UITableViewDelegate,前者决定了UITableView显示的内容,后者决定了UITableView的用户交互。我们先来实现UITableViewDataSource。
在EpisodeListViewController.swift里,添加下面的代码:
class EpisodeListViewController: UITableViewController {
// Omit for simplicity...
override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return 1;
}
}
和上一段视频中模拟的一样,我们使用tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)定义了UITableView的行数,为了演示,我们只是硬编码让它显示一行。
接下来,我们要来决定每一个Cell实际的内容,这是通过UITableViewDataSource的另一个方法实现的:
class EpisodeListViewController: UITableViewController {
// Omit for simplicity...
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCellWithIdentifier(
"EpisodeItem",
forIndexPath: indexPath)
return cell;
}
}
在这里,我们可以把indexPath理解为屏幕上不同Cell的位置。我们用之前在Storyboard里设置的Cell identifier,在每一个indexPath位置创建了一个UITableViewCell对象,然后把它返回给UITableView。
然后,按Command + R编译和执行,就能在模拟器里看到一个只有一行的UITableView了,而它的Cell,就是我们自定义的EpisodeItem。
"在这里,我们可以先忽略status bar覆盖了一部分UITableView的问题,稍后我们会处理它。"
特别提示
上面这两个方法,几乎是我们使用UITableViewController一定要定义的方法。但是,我们的Cell内容,每一行还都是相同的。我们将在下一段视频中,了解自定义Cell以及UITableView常见用户交互事件的处理方法。