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

再運行試一下,是否是怎麼上下拖動也不報錯了:)

相關文章
相關標籤/搜索