文档章节

关于UITableView的Cell复用谈谈一些心得

meilidashijie
 meilidashijie
发布于 2013/01/02 14:16
字数 1009
阅读 1525
收藏 6

查看博客:Rainbird的个人博客

UITableView是ios开发中使用率极高的一个控件,就我个人来说,几乎我做的每一个View上都有她的身影。但是很长一段时间,我对她的理解都很肤浅。对我来说触动较大的两个东西,一个是前面提到的自定义UITableViewCell,再有就是今天要提的这个复用了。
所谓复用表面意思来理解就是重复利用了。大致的工作原理就是:UITableView属于lazy loading,也就是只加载会在界面上显示的部分。举个例子,比如说UITabeview的调试是460,咱们每个Cell的调试是230,这样的话,手机界面上最多就显示两个Cell,当你向上划动,第一个Cell一些离开界面,第三个Cell的一些出现在界面的时候会再创建第三个Cell。注意关键部分到了,再第二个Cell开始离开界面,第四个Cell出现的时候,这时候不会创建第四个Cell,而是直接复用的第一个Cell!也就是说无论你的UITableView里有十条或者三十条数据,只会创建三个Cell来展示这些数据!

总的来说,这种工作机制很合理,无论从CPU和内存的角度考虑都很节省资源,但是这里有一个问题就是:这种机制是用来展示结构一样的数据的!很多时候我们总要实现动态加载,总要有一个Cell,与其它的Cell不同,用来显示“正在加载中”或者“加载更多”之类的东西。这时候在Cell复用的机制下会出现重叠的现像!
ok,光说不练,没啥用,简单演示一下:

  _objects = [[NSMutableArray alloc] init];
  for (int i = 0; i < 10; i++) {
    [_objects addObject:[NSString stringWithFormat:@"text %d",i]];
  }
  [_objects addObject:@"加载更多"];
  for (int i = 0; i < 10; i++) {
    [_objects addObject:[NSString stringWithFormat:@"text %d",i]];
  }

我们在一个数组里加了21条数据,而且中间那条不一样,属于我们说的数据结构不一致的那种。
cell展示部分我们是这么写的:

  NSString *_text = [_objects objectAtIndex:indexPath.row];
  
  //我们希望“加载更多”这行是居中显示
  if (![_text hasPrefix:@"text"]) {
    cell.textLabel.textAlignment = UITextAlignmentCenter;
  }

  cell.textLabel.text = _text;

ok,我们运行一下:

向下拖动一下,目前看来是没有问题的。可是当我们上下拖动了几次以后,问题出现了。。

由于cell的复用机制,“文本居中”(UITextAlignmentCenter)这种属性渐渐的被其它Cell用上了。这个肿么办呢?最早的时候,我通过了网上搜索,大家都说这是Cell的复用的问题。而我想当然的认为,既然是复用,那我就不复用就好了。于是我把

  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  }

改成了:

  if (cell != nil) {
    [cell release];
  }
  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
  cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

是的,在我这么改完以后,UITableView看起来确实是按我想的方式工作了,事实上很长的时间里都没再出过错。(不要问我为什么不在if后面跟个else把文本的属性设成“文本居左”(UITextAlignmentLeft),因为实际的数据比这复杂的多。)这种方法一直工作的很ok(确切的说是在iphone4上),直到很久以后,我把同样的程序在itouch上一跑,没载入多少条数据就提示Received memory warning了。。。。。
所以我知道了正确的Cell复用的方式:

  NSString *_text = [_objects objectAtIndex:indexPath.row];
  
  UITableViewCell *cell;
  if ([_text hasPrefix:@"text"]) {
    static NSString *CellIdentifier = @"Cell";
    
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                     reuseIdentifier:CellIdentifier] autorelease];
      cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
  }
  else {
    static NSString *CellIdentifier = @"CellReuse";
    
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                     reuseIdentifier:CellIdentifier] autorelease];
      cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    
    cell.textLabel.textAlignment = UITextAlignmentCenter;
  }
  

  cell.textLabel.text = _text;、

这可以这样:

static NSString *normalCellIdentifier = @”Normal Cell”;
static NSString *specialCellIdentifier = @”Special Cell”;

NSString *CellIdentifier;
if ([_text hasPrefix:@"text"]) CellIdentifier = normalCellIdentifier;
else CellIdentifier = specialCellIdentifer;

cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}

再运行试一下,是不是怎么上下拖动也不报错了:)

© 著作权归作者所有

meilidashijie
粉丝 14
博文 34
码字总数 16292
作品 0
海淀
私信 提问
加载中

评论(2)

meilidashijie
meilidashijie
JoeyBlue
JoeyBlue
就是使用CellIdentifier标记两种情况啊
UITableView 一些方法

1. UITableView的初始化 [csharp] view plain copy UITableView tableview= [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 420)]; [tableview setDelegate:self]; [tableview s......

晨曦之光
2012/05/16
852
0
iOS UITableView代理方法详解

iOS UITableView的代理方法详解 一、补充 在上一篇博客中,http://my.oschina.net/u/2340880/blog/404605,我将IOS中tableView(表视图)的一些常用方法总结了一下,这篇将tableView的代理方法...

珲少
2015/04/22
0
2
iOS开发小技巧:刷新UITableView

在很多APP界面都用到的UITableView,对iOS开发者来说一定不陌生吧。网上关于UITableView的文章早已多不胜数,尤其是关于UITableView优化方面的,对开发者来说非常值得一看。 现在就来看看,刷...

flyurt
2015/10/23
1K
0
UITableView 基本使用方法总结

首先,Controller需要实现两个 delegate ,分别是 UITableViewDelegate 和 UITableViewDataSource 2.然后 UITableView对象的 delegate要设置为 self。 3. 然后就可以实现这些delegate的一些方...

悠哉悠哉e
2012/11/13
0
0
关于UITableView你知道多少——UITableView简单解析

转自萧宸宇的博客 UITableView是在iOS开发中,展示大量内容的首选。我个人认为的原因有以下几点: 1.UITableView的展现形式是为移动设备专门设计过的。有较好的人机交互体验。 2.从技术角度来...

浪子艾菲儿
2013/08/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

未来,哪些技术在前端开发的地位会越来越高?

转眼2019也快走到下半年,过去的这段时间里,不论是互联网巨头还是初创企业,都纷纷进行了一波优化。渐趋理智的资本淘汰了一批不能适应市场的业务,而业务的紧缩也淘汰了一批不能适应市场的程...

智云编程
27分钟前
0
0
Golang math基本数学函数

三角函数 正弦函数,反正弦函数,双曲正弦,反双曲正弦 func Sin(x float64) float64 func Asin(x float64) float64 func Sinh(x float64) float64 func Asinh(x float64) float64 一次性返回......

Sunki
29分钟前
0
0
SpringBoot系列教程JPA之新增记录使用姿势

SpringBoot系列教程JPA之新增记录使用姿势 上一篇文章介绍了如何快速的搭建一个JPA的项目环境,并给出了一个简单的演示demo,接下来我们开始业务教程,也就是我们常说的CURD,接下来进入第一...

小灰灰Blog
今天
7
0
大话文本检测经典模型:Pixel-Anchor

文本检测是深度学习中一项非常重要的应用,在前面的文章中已经介绍过了很多文本检测的方法,包括CTPN(详见文章:大话文本检测经典模型CTPN)、SegLink(详见文章:大话文本检测经典模型Seg...

雪饼
今天
2
0
手把手教你写一个RPC

1.1 RPC 是什么 定义:RPC(Remote Procedure Call Protocol)——远程过程调用协议 ,RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC...

我最喜欢三大框架
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部