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