IOS開發之解決重用TableViewCell導致的介面錯亂的問題

來源:互聯網
上載者:User

標籤:

  無論是初學者,又或者是老鳥,只要是學習IOS的人都知道,TableView對於開發有多重要,然後我們在使用TableView,可能會遇到各種各樣的問題,例如今天我想要說的 TableViewCell的重用的問題:

  我們都知道,在TableView返回每一行cell的資料來源方法中,我們一般會通過重用cell來達到節省記憶體的目的:通過為每個cell指定一個重用標識符(reuseIdentifier),即指定了儲存格的種類,當cell滾出螢幕時,會將滾出螢幕的儲存格放入重用的緩衝池中,當某個未在螢幕上的儲存格要顯示的時候,就從這個緩衝池中取出儲存格進行重用。

但對於多變的自訂cell,有時這種重用機制會出錯。我舉個簡單的例子,看下面的兩張圖片 

<1>正常顯示的圖片

 

 

<2>介面錯亂的圖片

通過比較以上兩張圖片 明顯可以看出 第二張圖片的介面顯示錯亂,原因很簡單 ,那就是在重用cell的時候出現了問題,那麼我們該怎麼解決介面錯亂或者其他的問題呢?下面我一一為大家來介紹:

 

方法1 :

將獲得cell的方法從- (UITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier 換為-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath

重用機制調用的就是dequeueReusableCellWithIdentifier這個方法,方法的意思就是“出列可重用的cell”,因而只要將它換為cellForRowAtIndexPath(只從要更新的cell的那一行取出cell),就可以不使用重用機制,因而問題就可以得到解決,雖然可能會浪費一些空間。

//下面是範例程式碼:

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

    static NSString *CellIdentifier = @"Cell"; 
    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //改為以下的方法 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; //根據indexPath準確地取出一行,而不是從cell重用隊列中取出 
    if (cell == nil) { 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

}......

上面的代碼,無疑是能夠解決介面錯亂的問題,但如果資料很多,那就會浪費相當多的空間,不推薦使用。

 

方法2:

為每個cell指定不同的重用標識符(reuseIdentifier)來解決。
重用機制是根據相同的標識符來重用cell的,標識符不同的cell不能彼此重用。於是我們將每個cell的標識符都設定為不同,就可以避免不同cell重用的問題了。

怎麼為每個cell都設定不同的標示符呢?其實很簡單 在返回每一行cell的資料來源方法中 通過為每一個cell的標示符綁定indexPath.section--indexPath.row就可以了,下面是範例程式碼:

//實現建立cell的具體內容

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

    

    static NSString * ID = [NSString stringWithFormat:@"cell-ld%-ld%",[indexPath section ],[indexPath row]];

    //2.到緩衝池中去尋找可重用標示符

    HMWeiboCell * cell = [tableView dequeueReusableCellWithIdentifier:ID];

    if (cell == nil) {

        cell = [[HMWeiboCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];

    }

 

    //給cell中得屬性framemodel賦值

    HMWeiboFrameModel * frameModel = self.weiboFrameArray[indexPath.row];

    cell.weiboFrameModel = frameModel;

    return cell;

}

//上面的這種方式 雖然說比第一種方式有了一定的改進,通過為每一個cell都綁定了一個不同的標識符能夠使得cell與cell之間不會重用,解決了介面錯亂的問題,但是從根本上來說還是沒有太大的記憶體最佳化,同樣的如果資料比較多還是比較浪費空間。

 

方法3:

 

  第三種方式其實很簡單就是刪除重用cell的所有子視圖,這句話什麼意思呢?當我們從緩衝池中取得重用的cell後,通過刪除重用的cell的所有子視圖,從而得到一個沒有特殊格式的cell,供其他cell重用。是不是還是沒懂什麼意思,那我們就接著來看代碼:

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

{

    static NSString *ID = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; //出列可重用的cell

    if (cell == nil) {

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

    }

    else

    {

        //刪除cell的所有子視圖

        while ([cell.contentView.subviews lastObject] != nil)

        {

            [(UIView*)[cell.contentView.subviews lastObject] removeFromSuperview];//強制裝換為UIView類型 ,移除所有子視圖

        }

    }

    return cell;

}  

  看完上面的代碼是不是感覺這種方式很新穎,這種方式相比前兩種方式來說 是比較完美的,既達到了重用的目的,又不會導致介面的錯亂等問題,如果你也遇到了 自訂cell的時候 介面錯亂不堪,不妨試試這種方式吧,你會覺得很神奇的... 

 

方法4:

  看完了前面三種方式,你是不是覺得就沒有後文了呢,你錯了,下面我再來說說第四種方式:

  這第四種方式其實是比較笨的方法,為什麼這麼說呢,我們可以這麼來想,既然重用cell導致介面錯亂的原因是,重用cell的時候 資料沒有更換,將重用cell的資料一起重用了,那麼我們為什麼想不到在給自訂cell設定資料的時候 通過判斷每一個cell該使用什麼樣的資料呢 ,如果每一個cell使用的資料是不同的,那麼就不會導致介面的資料或者是frame出現問題了,下面我就用簡單的的例子來為大家示範:

 

    //如果是某一個軟體的會員 那麼會員表徵圖的frame設定 如果不是會員那麼重新設定 這樣就能夠解決會員表徵圖的資料和frame問題

    if (weiboModel.vip) {//如果是會員

        CGFloat vipX = CGRectGetMaxX(_nameF) + kMargin;

        _vipF = CGRectMake(vipX, kMargin, kVipWidth, kVipWidth);

    } else{

        _vipF = CGRectZero;

    }

再比如

    //設定picture的frame 注意也要判斷是否有picture

    if (weiboModel.picture.length>0) {//有圖片     

        CGFloat pictureY = CGRectGetMaxY(_textF) + kMargin;

        _pictureF = CGRectMake(kMargin, pictureY, kPictureWidth, kPictureWidth);

        //如果有圖片行高就是最大的圖片的y值加一個邊距

        self.cellHeight = CGRectGetMaxY(_pictureF) + kMargin;

    }else {

        _pictureF = CGRectZero;   

        //如果沒有圖片 最大的行高就是本文的最大高度加一個高度

        self.cellHeight = CGRectGetMaxY(_textF) + kMargin;

    } 上面這句代碼的目的是 當有圖片的時候 給圖片設定frame  如果沒有圖片那麼我們就設定frame為0,這樣就能輕鬆的解決frame導致的介面錯亂的問題了。

  以上四種方式,有自己的拙見,也有借鑒網上各位大牛的方法,希望這篇文章能夠對大家有協助,有什麼問題可以留言,我定將知無不言,言無不盡....

IOS開發之解決重用TableViewCell導致的介面錯亂的問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.