表视图是iOS开发中使用最频繁的视图,我们一般都会选择以表的形式来展现数据,比如通讯录、频道列表等。表视图分段、分组、索引等功能使我们所展示的数据看起来更规整更有调理,更令人兴奋的是表视图还可以利用细节展示等功能多层次的展示数据,正所谓一表胜千言。 不过,相较于其它控件表视图的使用比较复杂,但是对比于表视图各种灵活多变的功能,我们在使用上花费的努力还是相当值得的。
简单表视图
表视图的形式灵活多变,本着由浅入深的原则,我们先从简单表视图开始学习。本节讲的简单表视图是动态表,(iOS 5之前全部是动态表没有动态表和静态表区别)。
创建简单表视图
在iOS 5之后我们可以使用xib或者故事板技术创建表视图,要显示的是一个最基本的表,我们只需实现UITableViewDataSource协议中必须要实现的方法即可,分别是tableView:numberOfRowsInSection:和tableView:cellForRowAtIndexPath:就可以了。:
构造方法initWithFrame:style:是在实例化表视图的时候调用,如果采用xib或故事板来设计表视图,那么表视图的创建是在实例化表视图控制器的时候完成的,表视图显示的时候会发出tableView:numberOfRowsInSection:消息询问当前节中的行数,表视图单元格显示的时候会发出tableView:cellForRowAtIndexPath:消息为单元格提供显示数据。
我们创建一个简单表视图,单元格使用默认样式,有图标和主标题,显示的是世界杯球队的信息。
使用“Single View Application”模板创建一个工程,工程名为“SimpleTable”,打开IB设计画面,在“View Controller Scene”选中“View Controller”删除控制器,然后从控件库中拖拽一个“Table View Controller”到设计画面。
将h文件中ViewController的父类从原来的UIViewController修改为UITableViewController。
在IB设计画面左侧的Scene列表中选择“Table View Controller Scene” → “Table View Controller”, 打开表视图控制器的标识检查器,在Class选项里选择“ViewController”,这是我们自己的编写视图控制器。
然后在Scene列表中选择“Table View Controller Scene” → “Table View Controller” → “Table View”, 打开表视图的属性检查器。Content下有两个选项“Dynamic Prototypes”和“Static Cells”,这两个选项只有在故事板中才有。“Dynamic Prototypes”是构建“动态表”
如果通过代码来实现单元格的创建,“Prototype Cells”项目要设为0,代码实现的模式代码如下:
static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; }
Identifier是可重用单元格标识符,这个可重用单元格与Collection视图中的可重用单元格概念一样。首先,在表视图中查找是否有可以重用的单元格,如果没有就通过initWithStyle: reuseIdentifier:构造方法创建一个单元格对象。
如果要利用故事板设计单元格,要选择“Table View Controller Scene” → “Table View Controller” → “Table View” → “Table View Cell”,打开单元格的属性检查器,Style下有很多选项, Identifier是指可重用单元格标识符。
这样操作以后在代码部分就不需要实例化单元格了,我们直接通过设定的Identifier取得单元格的实例,以此达到重用单元格的目的。
static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } 我们需要将“team.plist”和“球队图片”添加到工程中,ViewController.h文件的代码如下: #import <UIKit/UIKit.h> @interface ViewController : UITableViewController @property (nonatomic, strong) NSArray *listTeams; @end
需要将ViewController的父类修改为UITableViewController。还定义NSArray*类型的属性listTeams,listTeams用来装载从文件中读取的数据。读取属性列表文件team.plist的操作是在viewDidLoad方法中实现的
ViewController.m文件的viewDidLoad方法代码如下:
- (void)viewDidLoad { [super viewDidLoad]; NSBundle *bundle = [NSBundle mainBundle]; NSString *plistPath = [bundle pathForResource:@"team" ofType:@"plist"]; //获取属性列表文件中的全部数据 self.listTeams = [[NSArray alloc] initWithContentsOfFile:plistPath]; } 我们再看看UITableViewDataSource协议方法,代码如下: - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.listTeams count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”CellIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } NSUInteger row = [indexPath row]; NSDictionary *rowDict = [self.listFilterTeams objectAtIndex:row]; cell.textLabel.text = [rowDict objectForKey:@"name"]; NSString *imagePath = [rowDict objectForKey:@"image"]; imagePath = [imagePath stringByAppendingString:@".png"]; cell.imageView.image = [UIImage imageNamed:imagePath]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; }
由于当前的这个表事实上只有一个节,因此不需要对节进行区分,在tableView: numberOfRowsInSection:方法中直接返回listTeams属性的长度即可。tableView:cellForRowAtIndexPath:方法中NSIndexPath参数的row方法可以获得当前的单元格行索引。cell.accessoryType属性是设置扩展视图类型。
我们可以将单元格的样式UITableViewCellStyleDefault替换为其它三种,来体验一下其它的三种单元格样式的效果。
简单表案例运行结果