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

查看博客:Rainbird的我的博客 php

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,光说不练,没啥用,简单演示一下: ios

  _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的复用的问题。而我想固然的认为,既然是复用,那我就不复用就行了。因而我把 xcode

  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复用的方式: iphone

  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;
  }
  
ui

  cell.textLabel.text = _text;、 spa

这能够这样: 调试

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

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];
}

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

相关文章
相关标签/搜索