iOS Programming 8 (UITableView & UITableViewController)
UITableView在iOS中是一个很重要的概念,它会把数据像列表一样显示在屏幕上.首先需要介绍几个概念:
UITableView: 它是一个view,用于在屏幕上显示数据.它会向其对应的dataSource询问应该显示什么数据,然后再显示.对应的dataShource需要遵循UITableViewDataSourceProtocol.UITableView同时需要一个delegate,用来处理在UITableView上传出来的事件.这个delegate需要遵循UITableViewDelegateProtocol.UITableView需要一个view controller来与之协作.
UITableViewController同时兼顾了view controller, delegate和data source这三个角色.UITableViewController继承自UIViewController,所以它有自己的view,这个view就是UITableView.UITableViewController负责UITableView的准备和显示.同时UITableViewController遵循了UITableViewDataSource和UITableViewDelegateProtocol,所以它既是data source又是delegate.
UITableView UITableViewController对应的关系如下:

首先创建一个UITableViewController的子类.
1 2 | |
UITableViewController默认的初始化方法是initWithStyle:,这里的style可以是UITableViewStylePlain或者UITableViewStyleGrouped,不过在iOS7里面,两者的差别并不大.为了传给它一个style,我们可以让这个默认初始化方法调用另一个init方法,然后再到里面去调用默认的初始化方法:
1 2 3 4 5 6 7 8 | |
这个时候我们只是建立了一个UITableViewController,但是并没有把它加到view hierachy里面去,所以我们来到AppDelegate的application:didFinishLaunchingWithOptions方法,在里面初始化这个BNRItemsViewController并把它作为window的root controller.
1 2 | |
现在运行,可以看到已经有table view的效果了,但是里面没有数据

接下来我们就应该往里面加数据.需要复用在前几章建立的BNRItem类,这个类代表了具体的商品.接下来还需要建立一个BNRItemStore类,我们的tableview controller会从这个store里面获取数据.具体怎么建立的这里就不阐述了,总之这个store有createItem和allItems两个方法,前者用来创建item后者用来获取所有的item用来显示.现在我们可以创建50个item用于显示:
1 2 3 4 5 6 7 8 | |
当UITableView需要显示的时候,它会向data source发送一些消息,然后通过这些回馈判断应该显示多少行数据,每行都显示什么等等.UITableViewController有两个必须实现的方法,这两个方法被定义在了Protocol中,它们分别是tableView:numberOfRowsInSection和tableView:cellForRowAtIndexPath,前者是用来得到需要显示多少行,后者是用来告诉每行显示的数据的具体内容.因为我们一共建立了50条数据,所以可以用前面的方法来得到行数:
1 2 3 | |
在介绍后者之前,需要插入解释一个概念 – UITableViewCell,这个对象对应于table中每一行的数据,即table中的每一行都由一个UITableViewCell填充.这个对象有一个subview名叫contentView,它是用来具体显示数据的,以文本或图片的形式.这个contentView里有三个property:detailTextLabel textLabel imageView,今天我们将会用到第二个.
下面是方法的实现:
1 2 3 4 5 6 7 8 | |
首先建立一个cell,然后得到所有items,并根据传进来的indexPath获取到特定的item,然后把item的description赋给cell的textLabel.这个方法是在每一行需要显示的时候被调用,所以indexPath对应于table view中对应的行数.
再次运行,发现tableview被填充了数据:

有时候,由于需要显示的内容非常多,如果使用上面的方法需要每次都建立tableviewcell,这样非常耗时耗内存,一个解决方法是建立特定数量的cell把它们放到一个cell pool里,然后当下滑tableview的时候,从pool里面提取cell来显示数据,把刚刚消失的cell放回到pool里去.为了达到上面的效果,我们只需要做两处改变:
- 注册cell类
- 在
tableView:cellForRowAtIndexPath方法里面提取
我们可以在BNRTableViewController的viewDidLoad方法里注册:
1 2 3 4 | |
然后修改tableView:cellForRowAtIndexPath方法:
1 2 3 4 5 6 7 8 | |
这里有一个identifier参数叫做UITableViewCell,这是因为我们通常在pool里面会放着各种不同类型的cell,在注册和提取的时候都给identifier标上名相当于给它们贴了标签,想要什么类型的cell只需要在提取的时候带上同样的标签就可以了.