一个最简单的UITableView项目

1,006 阅读4分钟

一个最简单的UITableView项目

项目基本设置

Xcode并没有提供直接使用UITableView的项目模板,不过我们可以基于一个"Single View Application"手工打造一个。

新建一个叫做UITableViewDemo的"Single View Application",然后,按照下图的设置,我们禁用横屏模式:

image

"对于一个iPhone app来说,通常,我们也不会选择Upside down,因为来电的时候,Mic和听筒的位置是反的,这很容易给用户带来一些麻烦。"

特别提示


置换新的ViewController

打开Main.storyboard,选中场景中的"View Controller",然后删掉它(因为我们要换一个新的UITableView Controller进来):

image

然后,打开ViewController.swift,把ViewController改成EpisodeListViewController,并且,让它从UITableViewController继承:


class EpisodeListViewController: UITableViewController { }

然后,在项目列表里,我们把ViewController.swift文件名,修改为EpisodeListViewController.swift:

image

然后,返回Main.storyboard,在"Object library"里,拖一个UITableViewController进来:

image

在Identity inspector里,我们把class设置为:EpisodeListViewController:

image

这样,我们拖进来的UITableViewController就和EpisodeListViewController"关联"起来了。

"为Controller设置Custom class很重要,很多时候我们的代码不好用都是因为我们忘记了设置它。"

特别提示

最后,在"Attribute inspector"里,我们把新添加的UITableViewController设置为"Initial View Controller"。这时UITableViewController左边会出现一个大箭头:

image

这样,我们的UITableView就会做为默认的View被加载了。按Command + R,我们就能在模拟器里,看到一个空的UITableView了。

image


Table row Vs Table cell

接下来,在我们向UITableView中添加内容之前,我们要区分两个概念。实际上,我们的Table可能会包含很多内容,每一条记录都可以认为是Table中的一行。但实际上,iPhone的一屏只能显示有限的内容,我们无须为不需要显示的内容分配UI资源。于是,对于UITableView来说,屏幕上的每一行,我们用一个UITableViewCell对象表示。最终,我们用一组有限的UITableViewCell对象,显示了所有需要显示的内容。

image

实际上,当我们拖拽一个UITableView到Storyboard的时候,Xcode就已经为我们准备了一个UITableViewCell的原型了:

image

为了自定义这个Cell,我们可以在"Document outline"中选中它:

image

"当然,你也可以在Storyboard中选中它,但是,要确保你选中的是Cell而不是Table View。"

特别提示

然后,拖拽一个UILabel进来:

image

我们让它占满整个UITableViewCell,Xcode会给我们对齐的提示:

image

然后,重新选中"Table View Cell"(确保不要选中UILabel也不要选中Table View),在"Attribute inspector"中,把Accessory设置成"Disclosure indicator",这样Cell的右侧就会出现一个小箭头,表示点击后会切换到新界面:

image

接下来,我们要给这个Cell起一个"别名",它很重要。当我们需要在一个Table View里显示多种不同类型的Cell时,我们可以用这个"别名"来创建不同的Cell对象。选中Table View Cell,在"Attribute inspector"中,我们把identifier设置成:"EpisodeItem":

image

这样,一个UITableViewCell对象的基本设置就完成了。简单来说,可以总结成三个部分:

  1. 定制Cell UI;
  2. 设置Accessory;
  3. 设置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。

image

"在这里,我们可以先忽略status bar覆盖了一部分UITableView的问题,稍后我们会处理它。"

特别提示

上面这两个方法,几乎是我们使用UITableViewController一定要定义的方法。但是,我们的Cell内容,每一行还都是相同的。我们将在下一段视频中,了解自定义Cell以及UITableView常见用户交互事件的处理方法。