多類型UITableViewCell重用的正確姿態(tài)

對(duì)于iOS開(kāi)發(fā)者,UITableViewCell的重用是最基本的技能血公,初學(xué)者都應(yīng)該掌握的荷荤。對(duì)于它的原理我就不在此啰嗦了,這里我重點(diǎn)說(shuō)下导绷,如何以正確的姿態(tài)來(lái)重用多類型的UITableViewCell犀勒,正確重用cell不僅僅要重用cell視圖,還需要好好重用cell的子視圖妥曲。你是否做到了呢贾费?


單一類型cell重用

對(duì)于簡(jiǎn)單單一cell的tableView來(lái)講,它的重用我們大多會(huì)在代理方法里這樣寫(xiě):

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//設(shè)置重用標(biāo)識(shí)符
static NSString * Identifier = @"MineCell";
//通過(guò)Identifier取到cell
MineTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
//若cell不存在逾一,在進(jìn)行創(chuàng)建
if (!cell) {
    cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: Identifier];
}
    //用set方法取到對(duì)應(yīng)的model對(duì)cell賦值
    [cell cellModel:self.cellModelArr[indexPath.row]];
    return cell;
}

或者使用需要注冊(cè)cell的寫(xiě)法:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//設(shè)置重用標(biāo)識(shí)符
static NSString *Identifier = @"MineCell";
 MineTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath:indexPath];
  //用set方法取到對(duì)應(yīng)的model對(duì)cell賦值
  [cell setCellModel:self.cellModelArr[indexPath.row]];
  return cell;
}

上面的兩種寫(xiě)法都很簡(jiǎn)單铸本,由于是單一類型的cell重用,不會(huì)涉及到子視圖的重用遵堵,所以沒(méi)什么可講的箱玷。

多類型cell重用

在很多情況下,UITableView并不是單一的一種cell陌宿,而會(huì)包含多種cell锡足,每種cell類型樣式布局都有明顯區(qū)別。這樣來(lái)我們就不能用上面單一的cell重用方式了壳坪。 對(duì)于多類型cell你當(dāng)然可以對(duì)每個(gè)類型的cell創(chuàng)建對(duì)應(yīng)的.h .m文件舶得,并在使用時(shí)引入該 cell的頭文件即可。但可能是出于偷懶爽蝴,我更習(xí)慣統(tǒng)一處理這些cell沐批。把這些cell都寫(xiě)在一個(gè).h .m文件內(nèi),通過(guò)對(duì)不同類型cell設(shè)置對(duì)應(yīng)對(duì)cellStyle枚舉狀態(tài)來(lái)辨別他們蝎亚,這樣以來(lái)九孩,一個(gè)文件就足夠了。
下面就重點(diǎn)說(shuō)下單文件下多類型cell的重用发框。主要代碼如下:

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

static NSString * MineCellIdentifier = @"MineCellIdentifier";

 //通過(guò)注冊(cè)的cell獲取MineTableViewCell
 MineTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MineCellIdentifier forIndexPath:indexPath];

    //根據(jù)不同row或者也可以根據(jù)model內(nèi)容來(lái)區(qū)分cellStyle
    if (indexPath.row == 0) {
        //通過(guò)setMineCellStyle:方法對(duì)cell就行類型賦值躺彬,我們會(huì)在 setMineCellStyle:方法里對(duì)cell就行布局等定制化處理。
        cell.mineCellStyle = MineTableViewCellStyleOne;
    }else
    {
        cell.mineCellStyle = MineTableViewCellStyleTow;
    }
    //用set方法取到對(duì)應(yīng)的model對(duì)cell賦值
    [cell setCellModel:self.cellModelArr[indexPath.row]];
    return cell;
}

我們一般會(huì)在MineTableViewCell.h里定義類似MineTableViewCellStyle的枚舉類型梅惯,并實(shí)現(xiàn)mineCellStyle屬性宪拥,這樣就可以在對(duì)應(yīng)的tableView代理方法里通過(guò)setMineCellStyle:方法來(lái)針對(duì)不同cellStyle布局了。setMineCellStyle:方法內(nèi)部實(shí)現(xiàn)大概如下:

- (void)setMineCellStyle:(MineTableViewCellStyle)mineCellStyle
{
    _mineCellStyle = mineCellStyle;
   //為了避免cell重用引起的子視圖錯(cuò)亂铣减,我們會(huì)先把cell的子視圖給全不移除她君,下面會(huì)在對(duì)應(yīng)的cellStyle內(nèi)重新創(chuàng)建并添加到cell的contentView內(nèi)。
    for (UIView *view in self.contentView.subviews) {
        [view removeFromSuperview];
    }
    //對(duì)不同的類型進(jìn)行針對(duì)性的布局繪制操作
    switch (mineCellStyle) {
        case MineTableViewCellStyleOne:
        {
            //這里省略了布局約束的代碼
            NSArray *viewArray = @[self.bankNumTitleLb, self.bankNumLb];
            for (UIView *view in viewArray) {
                [self.contentView addSubview:view];
            }
           //進(jìn)行布局操作(此處省略不是本文重點(diǎn))
        }
            break;
        case MineTableViewCellStyleTow:
        {
            //這里省略了布局約束的代碼
            NSArray *viewArray = @[self.phoneNumTitleLb, self.phoneNumTextField];
            for (UIView *view in viewArray) {
                [self.contentView addSubview:view];
            }
             //進(jìn)行布局操作(此處省略不是本文重點(diǎn))
        }
            break;
        case MineTableViewCellStyleDefault:
        {
            //這里省略了布局約束的代碼
            NSArray *viewArray = @[self.verificationCodeTitleLb,
            self.phoneNumTextField,self.verificationCodeButton];
            for (UIView *view in viewArray) {
                [self.contentView addSubview:view];
            }
           //進(jìn)行布局操作(此處省略不是本文重點(diǎn))
        }
            break;
    }
}

到這里也許你覺(jué)得一切都沒(méi)什么問(wèn)題葫哗。但有經(jīng)驗(yàn)的開(kāi)發(fā)者可能已經(jīng)看出來(lái)問(wèn)題所在犁河。問(wèn)題出在setMineCellStyle:方法里的這句代碼:

    for (UIView *view in self.contentView.subviews) {
        [view removeFromSuperview];
    }

這句代碼很簡(jiǎn)單鳖枕,就是前面說(shuō)到為了解決cell重用時(shí)會(huì)出現(xiàn)子視圖的重用〗奥荩可是"解決"了子視圖的重用問(wèn)題宾符,那么新問(wèn)題來(lái)了,每次都把子視圖移除灭翔,重新創(chuàng)建既消耗內(nèi)存還占用時(shí)間魏烫,嚴(yán)重會(huì)出現(xiàn)滑動(dòng)出現(xiàn)卡頓現(xiàn)象,而且都刪除了重建還能叫重用嗎肝箱?最多是只是留了個(gè)cell的'殼',里面的'肉'可都是新建的啊哄褒。

因此:在通過(guò)設(shè)置多種cell枚舉類型來(lái)實(shí)現(xiàn)多樣式cell布局時(shí),要先判斷當(dāng)前重用的cellStyle 和 需要設(shè)置的cellStyle是否一致煌张,不一致時(shí)呐赡,才需要重新布局繪制。

修改后的主要代碼如下:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString * MineCellIdentifier = @"MineCellIdentifier";
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:MineCellOneIdentifier forIndexPath:indexPath];
    //獲取當(dāng)前重用cell的類型cellStyle
    MineCellStyle cellStyle = cell.mineCellStyle;
    switch (indexPath.section) {
        case 0:
        {
            //如果當(dāng)前重用的cellStyle 和 需要設(shè)置的cellStyle不一致時(shí)骏融,才進(jìn)行類型重制链嘀!
            if (cellStyle !=  MineTableViewCellStyleOne) {
                cell.mineCellStyle = MineTableViewCellStyleOne;
            }
             [cell setCellModel:self.cellModelArr[indexPath.row]];
        }
            break;
        case 1:
        {
            switch (indexPath.row) {
                case 0:
                {
                    if (cellStyle !=  MineTableViewCellStyleTow) {
                        cell.mineCellStyle = MineTableViewCellStyleTow;
                    }
                    [cell setCellModel:self.cellModelArr[indexPath.row]];
                }
                    break;
                case 1:
                {
                    if (cellStyle !=  MineTableViewCellStyleThree) {
                        cell.mineCellStyle = MineTableViewCellStyleThree;
                    }
                    [cell setCellModel:self.cellModelArr[indexPath.row]];
                }
                    break;
            }
        }
            break;
    }
    return cell;
}

這樣以來(lái)即實(shí)現(xiàn)了單文件下實(shí)現(xiàn)多cell類型的功能,又完美的解決了多cell的重用及性能問(wèn)題档玻,如有疏漏不足之處多多指出怀泊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市误趴,隨后出現(xiàn)的幾起案子霹琼,更是在濱河造成了極大的恐慌,老刑警劉巖凉当,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枣申,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡看杭,警方通過(guò)查閱死者的電腦和手機(jī)糯而,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泊窘,“玉大人,你說(shuō)我怎么就攤上這事像寒『姹” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵诺祸,是天一觀的道長(zhǎng)携悯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)筷笨,這世上最難降的妖魔是什么憔鬼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任龟劲,我火速辦了婚禮,結(jié)果婚禮上轴或,老公的妹妹穿的比我還像新娘昌跌。我一直安慰自己,他們只是感情好照雁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布蚕愤。 她就那樣靜靜地躺著,像睡著了一般饺蚊。 火紅的嫁衣襯著肌膚如雪萍诱。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天污呼,我揣著相機(jī)與錄音裕坊,去河邊找鬼。 笑死燕酷,一個(gè)胖子當(dāng)著我的面吹牛籍凝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悟狱,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼静浴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了挤渐?” 一聲冷哼從身側(cè)響起苹享,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浴麻,沒(méi)想到半個(gè)月后得问,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡软免,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年宫纬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膏萧。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漓骚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榛泛,到底是詐尸還是另有隱情蝌蹂,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布曹锨,位于F島的核電站孤个,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏沛简。R本人自食惡果不足惜齐鲤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一斥废、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧给郊,春花似錦牡肉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吩屹,卻和暖如春跪另,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背煤搜。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工免绿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人擦盾。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓嘲驾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親迹卢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辽故,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,522評(píng)論 25 707
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,125評(píng)論 29 470
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件腐碱、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,033評(píng)論 4 62
  • 這樣偷吃東西的日子沒(méi)過(guò)幾天誊垢,我的不會(huì)拍馬屁和完全不認(rèn)同和他們廚房是一類人的思維,導(dǎo)致我和他們說(shuō)不上什么症见,也想不到說(shuō)...
    ChanViva閱讀 158評(píng)論 0 0
  • 2017.10.20.星期五陰 今天廠里沒(méi)有活就不加班喂走,大女兒今天也回來(lái),我從廠里開(kāi)車(chē)去車(chē)站接她回家谋作,六...
    899037e3b5bb閱讀 171評(píng)論 0 1