打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
关于UITableView的Cell复用谈谈我的一些心得 | 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;
再运行试一下,是不是怎么上下拖动也不报错了:)
完整工程下载:
UITableViewCellReuse
当然了除了以上提到的两点,UITableView还有很多比你想的要优秀的地方没有提到,以后有机会有一一表述.
这么久了,想必博主已经找到正确的方法了。但还是帮博主充实一下评论吧 
 以感谢博主的诸多精彩分享。
确切的说,Cell复用下,如果有多种不同的cell,应该定义各自对应的不同Identifier。把重用的cell pool分成几个不同的queue,然后再根据需要的cell类型去对应的queue里取重用的cell就好了。
比如:
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];
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ios UITableView中Cell重用机制导致内容重复解决方法
tableview中cell的设置
tableView:cellForRowAtIndexPath:
如何用代码在UIViewController 中添加UITableView
stupid教程
版本升级之'initWithFrame:reuseIdentifier:' is deprecated
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服