一、UITableViewController类,继承自ViewController。UITableView继承自UIScrollView。
1、UITableViewController极大的简化了创建 UITableView的过程,减少甚至消除了直接处理表格实例所需的重复步骤。
2、UITableViewController负责处理表格式图布局的繁琐细节,可便捷的创建表格,为委托和数据源添加本地TableView实例并提供自动化表格协议支持。
二 、实现表格的3个关键元素:布局、数据(数据源)、交互(实现委托)。
1、布局
UITableViewStyle: UITableViewStylePlain // regular table view
UITableViewStyleGrouped // preferences style table view
注意:如果继承的UITableViewController类,那么在viewDidLoad方法中,千万不要加上[self.view addSubview:self.tableView];不然会崩溃。貌似是因为UITableViewController中已经有一个tableView变量,已经把这个tableView加进去了。
2、指定数据源
数据源负责联系路径和具体的UITableViewCell实例,并根据需要返回单元格。
索引路径: 是NSIndex的对象,描述通过数据树到达特定节点的路径,即它们的分段、行。有两个属性:section、row
创建:
重用机制:当单元格因滚屏而脱离表格可见区时,表格可以将其缓存到重用队列中。
用法:我们可标记单元格以备重用,然后根据需要从该队列中提取。
在分配新单元格时,必须检查重用单元格是否可用。如果表格对dequeueReusableCellWithIndentifier:的请求返回nil,那么就需 要分配一个新的单元格。
如果该方法返回一个单元格,可以使用对当前行和分段索引有意义的信息更新这个单元格,但不需要添加此单元格到重用队列。系统会为你处理所有细节。
目的:节省内存,更快、更便捷的提供单元格内容,特别是在用户滚动一个长列表时。
注意:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; ... return cell }
这段代码是默认自带的代码,我们一般会在下面接着写
三、单元格
1、单元格类型
共有4种:UITableViewCellStyleDefault、UITableViewCellStyleSubtitle、UITableViewCellStyleValue1、UITableViewCellStyleValue2
各个效果:
测试代码:

1 //返回在某indexPath处的cell 2 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 3 { 4 //尝试从重用队列中取出一个cell,如果返回nil,就要重新创建一个 5 // static NSString *CellIdentifier = @"BaseCell"; 6 // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 7 // if(!cell) 8 // { 9 // cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 10 // } 11 // cell.textLabel.text = [[UIFont familyNames] objectAtIndex:indexPath.row]; 12 13 UITableViewCellStyle style; 14 NSString *cellIndetifier; 15 switch (indexPath.row%4) { 16 case 0: 17 style = UITableViewCellStyleDefault; 18 cellIndetifier = @"default"; 19 break; 20 case 1: 21 style = UITableViewCellStyleSubtitle; 22 cellIndetifier = @"Subtitle"; 23 break; 24 case 2: 25 style = UITableViewCellStyleValue1; 26 cellIndetifier = @"Value1"; 27 break; 28 case 3: 29 style = UITableViewCellStyleValue2; 30 cellIndetifier = @"Value2"; 31 break; 32 } 33 34 UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIndetifier]; 35 if(!cell){ 36 cell = [[UITableViewCell alloc]initWithStyle:style reuseIdentifier:cellIndetifier]; 37 } 38 39 if(indexPath.row>3){ 40 cell.imageView.image = [UIImage imageNamed:@"0.png"]; 41 } 42 cell.textLabel.text = cellIndetifier; 43 cell.detailTextLabel.text = @"subtitle"; 44 return cell; 45 }
一个现象,如果一致滑动view,再滑上去,会发现前3个cell中也有图片了。思考这个现象发生的原因?
当前4个cell退出当前屏幕时,这四个cell被放入了重用队列,在向下滑动的过程中,系统不断的从重用队列中取出cell,然后画图、修改text。当我们再滑上去的时候,重用队列里的cell都已经被贴了图,而我们没有并没有对这些图片进行处理,所以这些图片还是会显示在cell中。
如果想让前3行一直不显示图片,也很简单,按照上面的分析,只需要把图片移除即可。加上代码
if(indexPath.row <= 3){ cell.imageView.image = nil; }
2、单元格颜色交替
3、自定义单元格
网上很多教程都是用xib实现的,现在我们尝试用代码实现。
新建两个类:新建MyCell类,继承自UITableViewCell,用来构造自己的cell;
新建MyCellContent类,继承自 NSObject,作为数据源,用来往我们的cell中填充数据。效果如下:
4、移除单元格选中时的高亮
单元格选中后有三种状态:UITableViewCellSelectionStyleNone(选中后没有任何颜色高亮),
UITableViewCellSelectionStyleBlue(蓝色) UITableViewCellSelectionStyleGray(灰色)
两种方法:
a、选中后不会有任何颜色变化,不推荐。
cell.selectionStyle = UITableViewCellSelectionStyleNone;
b、允许单元格高亮显示,但是在交互完成之后移除高亮显示
实现原理:在点击响应tableView:didSelectRowAtIndexPath:中,延时几秒后,调用deselectRowAtIndexPath:取消选中状态。
//选中indexPath处的这一行,点击响应 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"row is %d",indexPath.row); self.navigationItem.title = [[UIFont familyNames]objectAtIndex:indexPath.row]; //[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; [self performSelector:@selector(didSelectColorGone:) withObject:nil afterDelay:0.5f]; } -(void)didSelectColorGone:(id)sender { NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];//得到选中行的indexPath [self.tableView deselectRowAtIndexPath:indexPath animated:YES];//取消选中那一行 }
这里之所以用performSelector:方法间接调用,而不直接调用didSelectColorGone:方法,是因为用performSelector可以设置延时。
5、一些特殊的单元格控件
a、勾选 b、展开配件(蓝色的或灰色的朝右的小v型箭头)
6、显示删除控件
效果:图中的红色圆形标记以及右边的delete按钮。
删除单元格设置:[self.tableViewsetEditing:YESanimated:YES];//设置为可编辑的
实现的委托方法:
// Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { NSLog(@"commitEditingStyle StyleDelete called!"); // Delete the row from the data source // [self.tableView deleteRowsAtIndexPaths:indexPath withRowAnimation:UITableViewRowAnimationFade]; [self updateItemAtIndexPath:indexPath withString:nil]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } }
自己实现的删除方法:
- (void) updateItemAtIndexPath: (NSIndexPath *) indexPath withString: (NSString *) string { // You cannot insert a nil item. Passing nil is a delete request. NSLog(@"updateItemAtIndexPath called"); if (!string) [self.arry removeObjectAtIndex:indexPath.row]; else [self.arry insertObject:string atIndex:indexPath.row]; [self.tableView reloadData]; }
这里有个问题,我删除的明明是0000,结果后来实际删除的是4444,考虑应该是删除方法写的有问题。