UITableView相关
1、TableView的使用流程
1>将数据转换成模型
2>在控制器当中组合一个数据属性,重写getter方法,将字典转成模型
3>封装cell,组合一个模型属性到cell封装,重写setter方法,在其中设置frame和分发数据
4>在实现数据源返回UITableViewCell的方法中,用封装好的cell类创建cell对象,并给cell的模型属性赋值模型数据。
5>在cell类中分发数据
2、frame大模型使用(MCVC)
M
1>创建小模型;
2>创建一个模型类,组织进来所有子控件的frame属性,一个行高属性和一个模型属性;
3>重写(扩充)小模型属性的setter方法,在其中算frame和行高
C
4>在控制器容器属性的getter方法先将小模型转换成小模型;再创建一个frame大模型对象,将转化完的小模型赋值给frame大模型的小模型属性(这时会调用小模型属性的setter方法,计算出当前cell的所有子控件的frame和行高完成大模型转换,此时的frame模型当中包含cell创建会用到的所有信息包括布局信息和数据信息)小模型就会转成frame大模型,然后将大模型装入控制器的数据容器
V
5>在cell的类当中组合一个frame大模型的属性,并添加cell子控件属性
6>重写构造方法,在构造方法中添加子控件,并赋值给属性
7>创建快速构造器。添加可重用标识;查看是否存在可循环使用的cell在缓存池中;如果不存在则创建
8>重写(扩充)其setter方法,在其中设置当前cell的frame和数据分发
C
9>在实现数据源返回UITableViewCell的方法中,在创建完cell后,用数据容器给cell的frame模型属性赋值
3、定义cell
1>使用xib自定义cell(用于cell布局固定的时候)
a.创建xib文件和一个基于UITableViewCell的关联类与xib同名(可以让系统自动完成同时创建)
b.如果是xib文件和关联类是分别创建的,需要修改xib文件的class与关联类名
c.在xib文件当中完成布局
d.在关联类当中组合一个数据模型属性,并重写setter方法,在setter方法中分发数据,注意不要忘记这里是对setter方法扩充,应该首先完成setter方法本身的功能eg:_xxx = xxx;
e.添加快速构造器的加号方法。添加可重用标识;查看是否存在可循环使用的cell在缓存池中;如果不存在则创建
f.在控制器中使用快速构造器创建cell,并给cell的模型属性赋值
2>使用重代码自定义cell(用于cell布局变化的时候,通常高度会变eg:微博)
a.创建一个基于UITbaleViewCell的类
b.添加需要的子控件属性
c.在重写的减号构造方法中添加子控件,并将子控件赋值转成属性
d.在该类中添加一个快速构造器,在构造器当中添加可重用标识;查看是否存在可循环使用的cell在缓存池中;如果不存在则创建
e.在该类中组合进来一个模型属性(通常我们会组合一个包含数据模型的frame模型),并重写setter方法,在setter方法中完成frame设置和数据分发
3>使用系统cell(在系统cell能满足我们的情况下使用)
a.系统cell一般会包含一个textLabel,一个imageView,一个detailLabel和一个accessoryType(附件)
b.通常即使使用系统也会通过自定义的方法,但在创建的类中只做两件事:组合一个模型属性并重写setter方法,在其中分发数据;还有就是创建一个快速构造器,添加可重用标识;查看是否存在可循环使用的cell在缓存池中;如果不存在则创建
4、重用问题
1>cell重用
a.cell重用可能引发的问题,如:按钮的状态,vip状态,有的cell时没有的,或者状态不一样的。我们需要根据子控件最齐全的cell来分发数据,给每一个cell上可能出现的子控件每次都做一次数据分发,对于状态这些东西,可以根据属性判断,如果没有相关属性(例如监听点击事件的按钮状态)我们可以给,传入cell的模型上添加一个相关bool属性,来控制
b.cell的刷新(tableView调用reloadData方法)和滑动都会重用缓存池当中的
2>UITableViewHeaderFooter的重用(注意tableViewheaderfooter返回的是UIView)
a.headerfooter刷新的时候不会重用缓存池当中的headerfooter
b.滑动的时候会重用缓存池当中的headerfooter所以也需要考虑到cell重用一样的问题
5、UITableViewController的使用
1>系统自动实现部分
a.通常在整个环境只有一个tableView的时候使用,不需要设置代理为自己,设置遵循协议,(dataSource和delegate协议)以上操作有系统自动完成
b.此时的在控制器中的self.view和self.tableview都是指我们的tableview
2>程序员需要完成部分
c.通常如果我们要使用UITableViewController自带的tableViewCell(其实也是一个xib)会为添加一个相关的类来关联这个cell,这个类当中通常我只需要组合进来一个数据模型的属性,并重写奇setter方法用于设置数据,其他不用的部分可全部删除(基于UITableViewCell创建类,系统会自动生成一些代码)
d.需要修改控制器的class和其中tableViewCell的class方便连线使用
e.只要在stroyboard文件设置了重用标识,就可以实现重用可以直接在实现tableView的cell方法时候直接使用[tableViewdequeueReusableCellWithIdentifier:设置好的标示符]来创cell
5、cell的刷新、增、删和拖拽
1>滑动手势(向做滑动cell)
a.这里的滑动手势是指滑动删除手势;
b.滑动删除手势系统已经实现,而且是系统默认的cell编辑状态,只要向左滑动cell ,cell右侧出现一个“delete”按钮,点击就能出发删除事件,调用编辑方法(编辑方法中可以实现增、删cell);
c.这里的编辑方法就是UITableViewDataSource的代理方法- (void)tableView:commitEditingStyle:forRowAtIndexPath:,实现该方法,即可删除;
2’编辑模式
a.开启编辑状态设置tableView.editing = YES;
b.默认开启删除状态,会在cell的左侧出现一个“-”;如果想开启增加状态,需要实现UITableViewDelegate的代理方- (UITableViewCellEditingStyle)tableView:editingStyleForRowAtIndexPath:并返回增加模式,就会出现“+”用于增加cell;
c.点击“-”实现有滑动删除手势一样的功能,需要再点击右侧的“delet”调用编辑方法;点击“+”会直接调用编辑方法;
d.实现UITableViewDataSource的代理方法- (void)tableView:commitEditingStyle:forRowAtIndexPath:实现增加或者删除功能
e.具体实现UITableViewDataSource的代理方法,有两种方式实现:一个是直接删除或者增加模型数据(当然删除可以直接移除子控件,(其实也是移除数据)UIView通用方法removeObjectAtIndex:),然后调用reloadData重新加载数据,;另一个是直接调用deleteRows和insertRows开头的方法局部编辑;
eg:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
returnUITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle ==UITableViewCellEditingStyleDelete) {
NSLog(@"UITableViewCellEditingStyleDelete");
//整体删除
// 1. 删除这条数据
//[self.herosremoveObjectAtIndex:indexPath.row];
// 2. 刷新
//[self.tableView reloadData];
// 局部删除
[self.tableViewdeleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationLeft];
}elseif (editingStyle ==UITableViewCellEditingStyleInsert){
//整体增加
// 1. 添加数据
HMHero *hero = [[HMHeroalloc]init];
hero.name = @"孙猴子";
[self.herosinsertObject:heroatIndex:indexPath.row +1];
// 2. 刷新
// 局部添加
NSIndexPath *path = [NSIndexPathindexPathForRow:indexPath.row +1 inSection:indexPath.section];
[self.tableViewinsertRowsAtIndexPaths:@[path]withRowAnimation:UITableViewRowAnimationLeft];
}
}
3>拖拽
a.开启编辑模式tableView.editing = YES;
b.实现拖拽方法- (void)tableView:moveRowAtIndexPath:toIndexPath:,要实现下面的控件会往上顶(系统的默认操作就是这样)我们使用先保存要删除的cell数据,再删除该cell,最后将保存的数据再进行添加(如果方法实现为空,拖拽的当时,下面的控件会往上顶,但是刷新过后拖拽过的控件会回到原来位置)
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
}
4>刷新
a.全部刷新:直接调用reloadData即可;
b.局部刷新:直接调用reloadRows开头的方法即可
5>indexPath的构造(因为在局部刷新,增,删,拖动可能都会用到该数据)
+ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section;
6>- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
新特性
1、[self.tableView registerClass:[DHTableViewCell class] forCellReuseIdentifier:ID];
tableView用cell类名注册cell的重用标识为ID,这样在调用-dequeueReusableCellWithIdentifier:forIndexPath:的时候,如果没有可以循环利用的cell那么就会自动调用-initWithStyle:reuseIdentifier:来实例化一个cell
2、[self.tableView registerNib:[UINib nibWithNibName:@"DHTableViewCell" bundle:nil] forCellReuseIdentifier:ID];
tableView通过nib文件来注册cell的重用标识为ID,这样在调用-dequeueReusableCellWithIdentifier:forIndexPath:的时候,如果没有可以循环利用的cell,系统就会自动加载nib文件来创建cell
3、在ios6之前,没有重用标识,在使用nib描述cell的时候程序员只能手动加载nib文件来创建cell,或者alloc] init]的方法创建cell,并将其加入到循环利用池,ios6之后系统帮我们完成了这一操作,我们只需要在使用cell之前注册即可
4、ios6以后,我们只需要在cell使用之前注册cell,如果是nib描述可以考虑在-awakeFromNib中做些初始化工作;没有nib描述,考虑重写-initWithStyle:reuseIdentifier: