IOS tableViewCell單元格重用中的label重疊的問題


參考:http://zhidao.baidu.com/link?url=_oMUTo5SxUY6SBaxYLsIpN3i2sZ6SKG35MVlPJd2cNmUf9TGQFkKXX9EXwSwti0nX08gR8j4je4WPXzKq96Ts29r3aZBcLDDVMJdWLGYzCy

例1:

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

  static NSString *CellIdentifier = @"cell1";

  UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  if (cell == nil) {

  cell = [UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

  UILabel *labelTest = [UILabel alloc]init];

  [labelTest setFrame:CGRectMake(2, 2, 80, 40)];

  [labelTest setBackgroundColor:[UIColor clearColor];

  [labelTest setTag:1];

  [cell contentView]addSubview:labelTest];

  }

  UILabel *label1 = (UILabel*)[cell viewWithTag:1];

  [label1 setText:[self.tests objectAtIndex:indexPath.row];

  return cell;

  }

  例2:

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{

  static NSString *CellIdentifier = @"cell1";

  UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  if (cell == nil) {

  cell = [UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

  }

  UILabel *labelTest = [UILabel alloc]init];

  [labelTest setFrame:CGRectMake(2, 2, 80, 40)];

  [labelTest setBackgroundColor:[UIColor clearColor]; //之所以這里背景設為透明,就是為了后面讓大家看到cell上疊加的label。

  [labelTest setTag:1];

  [cell contentView]addSubview:labelTest];

  [labelTest setText:[self.tests objectAtIndex:indexPath.row];

  return cell;

  }

  當你上下來回滑動tableview的時候就會看到區別,第一種程序界面不會出現異常,但是第二種就不是了,會出現字體疊加現象,其實更確切的是多個label的疊加。為什么呢,因為在tableview刷新的時候,如果那個位置已經有現成的cell,它就不會再重新請求資源生成新的cell了,而是復用原來的cell。所以對於對於第一種,代碼的思路是第一次在cell不存在的時候生成cell,定義cell樣式,以后不管是刷新還是重新請求還好,它都只是復用已生成的cell。而第二種思路是,在cell不存在的時候,請求生成cell,然后給cell上添加label,刷新的時候,會復用已有的cell,但是會重復添加label,故造成重疊的現象。
http://m.blog.csdn.net/blog/heyehao2008/27806945
在使用TableView的時候,下面一段代碼是必須的,也是最標准的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {  
      
    static NSString *CMainCell = @"CMainCell";     //  0  
      
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CMainCell];  //  1  
    if (cell == nil) {  
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier: CMainCell] autorelease];// 2  
    }  
    // Config your cell  
        cell.textlabel.text = @"XXX";    //  3  
      
    return cell;  
}  

可以這樣理解,cell有一個地方(假設稱為隊列),專門存放那些生成過的,但是后來由於滾動tableView而隱藏起來的cell,而代碼中語句1就是從隊列中根據標示符取出一個暫時不用的cell,只有cell為nil,也就是隊列中沒有舊的cell的時候,才會執行語句2,生成一個新的cell。如果有舊的,就不用執行語句2了,這樣節省資源,算作一種重用吧。在tableView初始化的時候隊列中肯定沒有cell的,所以每個cell生成的時候都會執行一遍2,當屏幕顯示滿了,向上滾動顯示下一行時,就會把第一行隱藏,放到那個隊列中,然后新增加的一行執行語句1的時候,結果就不是nil了,然后,就跳過語句2了,這樣就節約資源了。

當然,上面這樣對於使用系統提供的cell格式是沒有什么問題,但是如果自己在cell上添加一些控件時,比如一個label,有時就會出現問題。尤其是各個cell的label的文字不相同時。首先這個添加的過程一定要在語句2之后,這樣才是一次添加,如果放在語句3之后,那么由於cell的重用可能舊的上面已經有label了,你再添加一個,造成多次添加。其次label的文本值必須保證每次都要重新設置,也就是在語句3之后設置,這樣才能保證每次必須執行。如果放在語句2后面,那么當使用舊的cell時,仍會保留舊的label文字,這是不對的。所以是在2后添加,在3后設置,可以在2添加的時候設一個tag值,這樣可以在3處通過tag值獲取控件設置。

關於語句0,如果每個cell的結構完全相同,那沒問題,就用這一個標識符,但是如果各個cell結構不完全相同,有的有textfield,有的有button,有的有switch,那就不能互相重用了,只能每行用不同的標識符了,可以方便的利用(@"CMainCell%d", indexPath.row),保證不會重復,多組的再加上組號。那這還有必要用語句2嗎?還是需要的,因為當自己滾動隱藏,下次再顯示出來的時候,還是可以重用的。標識符完全可以每次用一個新的,但為了最大限度的重用性,節省資源,才想了這么多辦法。

總之,注意添加控件的位置,注意設置控件的位置,注意cell標識符。
 
         
         
        
 
        
當我們的uitableview為透明或者判斷cell是否為空時,會發現uitableveiwcell會出現重疊,下面為自己的解決辦法,提供給各位參考
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell=nil;
    static NSString *reuse=@"cell";
    if (cell==nil) {
        cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuse] autorelease];
    }else{
        while ([cell.contentView.subviews lastObject] != nil) {  
            [(UIView*)[cell.contentView.subviews lastObject] removeFromSuperview];  //刪除並進行重新分配
        }  
    }
    
    cell.textLabel.text=@"cell";
    
    return cell;
}

 

另一種寫法

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdetify = @"cell";
    UITableViewCell *tvCell = [tableView dequeueReusableCellWithIdentifier:cellIdetify];
    
    if(tvCell == nil)
    {
        NSLog(@"cell = nil");
        tvCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdetify] autorelease];
    }else{
        NSLog(@"cell !=nil ");
        NSArray *views = [tvCell subviews];
        for (UIView *obj in views) {
            if (obj.tag==1000 || obj.tag==2000) {      //只刪除指定的畫面,不要全部刪除,否則tableview的分割線也會被刪除
                NSLog(@"cell 要刪除的子畫面是:%@",[obj class]);
                [obj removeFromSuperview];
            }
        }
 
        
 
        
轉載:http://www.cnblogs.com/ygm900/archive/2013/06/13/3134436.html
 
        

如何實現 cell的重用?

主要是通過 UITableView的 “dequeueReusableCellWithIdentifier” 函數來實現,從字面上理解是“出列的可重用的cell”,其實簡單說就是一個cell池,里面放的就是你之前創建過的cell。

注意點:

1,重取出來的cell是有可能已經捆綁過數據或者加過子視圖的,如果有必要,要清除需要用與顯示的數據和remove掉add過的子視圖(使用 tag—viewWithTag 獲取相關視圖對象)。

2,原理就是為了避免頻繁的 alloc和delloc cell對象。

3,設計的關鍵是實現cell和數據的完全分離。

介紹:一個屏幕顯示的cell數量是有限的,當屏幕滾動時候,就會調用方法獲取新的cell,而老的cell會在屏幕外面就不顯示了。reuse機制就是這樣,當cell需要顯示的時候,從queue里面找,找到了,設置一下內容,顯示出來。滾動界面當有cell被移出屏幕時,把這個cell丟到queue里面,顯示新的cell時,如果有“相同類型”(identifier)的cell,就從隊列拿一個出來,設置數據,顯示出來,至於queue里面會有多少cell,這個會自動控制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM