iOS开发常用控件之UITableView

UITableView可以说是iOS开发中最常用的控件之一了,常用于展示表单及列表类数据。

UITableView

如何展示数据

设置数据源对象

1
self.tableView.dataSource = self;

数据源对象要遵守协议

1
2
3
@interface ViewController () <UITableViewDataSource>

@end

实现数据源方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

// 每一组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

// 每一行显示什么内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

// 每一组的头部
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;

// 每一组的尾部
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section

tableView的常见设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 设置每一行cell的高度
self.tableView.rowHeight = 100;

// 设置每一组头部的高度
self.tableView.sectionHeaderHeight = 50;

// 设置每一组尾部的高度
self.tableView.sectionFooterHeight = 50;

// 设置分割线颜色
self.tableView.separatorColor = [UIColor redColor];
// 设置分割线样式
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// 设置表头控件
self.tableView.tableHeaderView = [[UISwitch alloc] init];
// 设置表尾控件
self.tableView.tableFooterView = [UIButton buttonWithType:UIButtonTypeContactAdd];

// 设置右边索引文字的颜色
self.tableView.sectionIndexColor = [UIColor redColor];
// 设置右边索引文字的背景色
self.tableView.sectionIndexBackgroundColor = [UIColor blackColor];

UITableViewCell

UITableViewCell的常见设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 设置右边的指示样式
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

// 设置右边的指示控件
cell.accessoryView = [[UISwitch alloc] init];

// 设置cell的选中样式
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// backgroundView优先级 > backgroundColor

// 设置背景色
cell.backgroundColor = [UIColor redColor];

// 设置背景view
UIView *bg = [[UIView alloc] init];
bg.backgroundColor = [UIColor blueColor];
cell.backgroundView = bg;

// 设置选中的背景view
UIView *selectedBg = [[UIView alloc] init];
selectedBg.backgroundColor = [UIColor purpleColor];
cell.selectedBackgroundView = selectedBg;

cell的循环利用

传统的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/** 每当有一个cell要进入视野范围内,就会调用一次
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"wine";

// 1.先去缓存池中查找可循环利用的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

// 2.如果缓存池中没有可循环利用的cell
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}

// 3.设置数据
cell.textLabel.text = [NSString stringWithFormat:@"%zd行的数据", indexPath.row];

return cell;
}

新的写法(注册cell)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
NSString *ID = @"wine";

- (void)viewDidLoad {
[super viewDidLoad];

// 注册某个重用标识 对应的 Cell类型
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.先去缓存池中查找可循环利用的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

// 2.设置数据
cell.textLabel.text = [NSString stringWithFormat:@"%zd行的数据", indexPath.row];

return cell;
}

cell的高度的新的计算方式

  • iOS8新增加预估高度(self-sizing)
1
2
3
4
// 告诉tableView所有cell的高度是自动计算的(根据设置的约束)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 设置一个预估值
self.tableView.estimatedRowHeight = 44 ; //44为任意值

自定义下划线

  • 不需要去掉原来的下划线,就可以实现在有内容的时候,下面显示出下划线,没有内容的地方不会出现下划线。
1
2
// 添加分割线的取巧方法
self.tableView.tableFooterView = [[UIView alloc] init];
  • 另一种自定义下滑线的方式就是在cell最下面自定义一个高度为1的UIView,这种方法需要去掉原来的下划线。
1
2
// 去掉自带的分割线
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

如何利用xib封装一个cell

  • 新建一个xib文件描述一个cell的内部结构
  • 新建一个新的类(继承自UITableViewCell)
  • 新建类的类名最好跟xib的文件名保持一致
  • 将xib中的控件 和自定义的类 进行连线
  • 提供一个类方法快速返回一个创建好的自定义的view(屏蔽从xib加载这个过程)
hack_appList_result_failed

通过代码自定义cell(cell的高度不一致)

  • 新建一个继承自UITableViewCell的类
  • 重写initWithStyle:reuseIdentifier:方法添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中)进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
  • 提供2个模型
    • 数据模型: 存放文字数据\图片数据
    • frame模型: 存放数据模型\所有子控件的frame\cell的高度
  • cell拥有一个frame模型(不要直接拥有数据模型) (重写set方法)
  • 重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
  • frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)
hack_appList_result_failed

数据刷新

  • 添加数据
  • 删除数据
  • 更改数据

全局刷新方法(最常用)

  • 屏幕上的所有可视的cell都会刷新一遍
1
[self.tableView reloadData];

局部刷新方法

  • 添加数据
1
2
3
NSArray *indexPaths = @[[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0]];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
  • 删除数据
1
2
3
NSArray *indexPaths = @[[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0]];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];
  • 更新数据(没有添加和删除数据,仅仅是修改已经存在的数据)
1
2
3
NSArray *indexPaths = @[[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0]];
[self.tableView relaodRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];

左滑出现删除按钮

  • 需要实现tableView的代理方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 只要实现了这个方法,左滑出现Delete按钮的功能就有了
* 点击了“左滑出现的Delete按钮”会调用这个方法
*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// 删除模型
[self.wineArray removeObjectAtIndex:indexPath.row];

// 刷新
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}

/**
* 修改Delete按钮文字为“删除”
*/
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"删除";
}

左滑出现N个按钮

  • 需要实现tableView的代理方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 只要实现了这个方法,左滑出现按钮的功能就有了
(一旦左滑出现了N个按钮,tableView就进入了编辑模式, tableView.editing = YES)
*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {}

/**
* 左滑cell时出现什么按钮
*/
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"点击了关注");

// 收回左滑出现的按钮(退出编辑模式)
tableView.editing = NO;
}];

UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
[self.wineArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}];

return @[action1, action0];
}

进入编辑模式

1
2
3
// self.tabelView.editing = YES;
[self.tableView setEditing:YES animated:YES];
// 默认情况下,进入编辑模式时,左边会出现一排红色的“减号”按钮

在编辑模式中多选

1
2
3
4
5
6
7
// 编辑模式的时候可以多选
self.tableView.allowsMultipleSelectionDuringEditing = YES;
// 进入编辑模式
[self.tableView setEditing:YES animated:YES];

// 获得选中的所有行
self.tableView.indexPathsForSelectedRows;
要不要鼓励一下😘