UITableView

一、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
}

这段代码是默认自带的代码,我们一般会在下面接着写

if(!cell){         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];     }
但是,这样运行的时候是会崩溃的,加断点发觉是在 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 这句话崩溃的。这是为什么了?
跟踪进去发觉这个方法有个标注:NS_AVAILABLE_IOS(6_0);也就是说他只能在6.0以上的版本运行。换成另一个方法
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];就可以了。至于新方法怎么用,可参考这篇帖子:http://bbs.csdn.net/topics/390330467上面有这两个方法的解释。

          

 三、单元格

 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 Code

一个现象,如果一致滑动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,考虑应该是删除方法写的有问题。

    

原文地址:https://www.cnblogs.com/wyqfighting/p/3171902.html