tableView重用機(jī)制

一 重用機(jī)制簡(jiǎn)介

首先我們需要搞明白為什么要使用重用機(jī)制,它的原理是什么.

無(wú)論是UITableView還是UICollectionView温自,都有許多需要顯示的cell (item), 但是屏幕的大小是有限的,一次只能顯示那么幾個(gè)德迹,如果我們把所有的數(shù)據(jù)全部都加載進(jìn)去,暫時(shí)又看不到,就會(huì)非常浪費(fèi)內(nèi)存.

那么該如何避免這種不必要的內(nèi)存消耗呢胃碾?就是每次只顯示屏幕能放得下的cell的數(shù)據(jù)易稠,在用戶滑動(dòng)屏幕的過(guò)程中,再去加載新的數(shù)據(jù)吟秩,于是就有了cell的重用機(jī)制

重用機(jī)制實(shí)現(xiàn)了數(shù)據(jù)和顯示的分離,并不會(huì)為每個(gè)要顯示的數(shù)據(jù)都創(chuàng)建一個(gè)Cell,一般情況下只創(chuàng)建屏幕可顯示的最大的cell個(gè)數(shù)+1,每當(dāng)有一個(gè)cell從屏幕消失咱扣,就將其放到緩存池中,如果有新的cell出現(xiàn)涵防,就去緩存池中取闹伪,如果緩存池中沒(méi)有,再創(chuàng)建。

---->這種機(jī)制下系統(tǒng)默認(rèn)有一個(gè)可變數(shù)組 NSMutableArray* visiableCells, 用來(lái)保存當(dāng)前顯示的cell. 還有一個(gè)可變字典 NSMutableDictnery* reusableTableCells, 用來(lái)保存可重復(fù)利用的cell. 之所以用字典是因?yàn)榭芍赜玫腸ell有不止一種樣式,我們需要根據(jù)它的reuseIdentifier(重用標(biāo)識(shí)符)來(lái)查找是否有可重用的該樣式的cell.

二 重用機(jī)制簡(jiǎn)介如何解決一些重用cell

1.cell創(chuàng)建使用[tableView cellForRowAtIndexPath:indexPath]

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 
    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //改為以下的方法 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; //根據(jù)indexPath準(zhǔn)確地取出一行偏瓤,而不是從cell重用隊(duì)列中取出 
    if (cell == nil) { 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
    } 
     //...其他代碼                               
} 

將獲得cell的方法從- (UITableViewCell)dequeueReusableCellWithIdentifier:(NSString)identifier 換為-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath杀怠;重用機(jī)制調(diào)用的就是dequeueReusableCellWithIdentifier這個(gè)方法,方法的意思就是“出列可重用的cell”厅克,因而只要將它換為cellForRowAtIndexPath(只從要更新的cell的那一行取出cell)赔退,就可以不使用重用機(jī)制,因而問(wèn)題就可以得到解決证舟,但是會(huì)浪費(fèi)一些空間硕旗。(不建議使用)

2.不同標(biāo)識(shí)符

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

    NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];//以indexPath來(lái)唯一確定cell 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //出列可重用的cell 
    if (cell == nil) { 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
    } 
    //...其他代碼 
} 

通過(guò)為每個(gè)cell指定不同的重用標(biāo)識(shí)符(reuseIdentifier)來(lái)解決。重用機(jī)制是根據(jù)相同的標(biāo)識(shí)符來(lái)重用cell的女责,標(biāo)識(shí)符不同的cell不能彼此重用漆枚。于是我們將每個(gè)cell的標(biāo)識(shí)符都設(shè)置為不同,就可以避免不同cell重用的問(wèn)題了抵知。

3.刪除重用cell的所有子視圖

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //出列可重用的cell 
    if (cell == nil) { 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
    } 
    else 
    { 
        //刪除cell的所有子視圖 
        while ([cell.contentView.subviews lastObject] != nil) 
        { 
            [(UIView*)[cell.contentView.subviews lastObject] removeFromSuperview]; 
        } 
    } 
    //...其他代碼 
}

這個(gè)方法是通過(guò)刪除重用的cell的所有子視圖墙基,從而得到一個(gè)沒(méi)有特殊格式的cell,供其他cell重用辛藻〉忾伲考慮到內(nèi)存問(wèn)題,cell少得時(shí)候可以每個(gè)都添加標(biāo)識(shí)符,當(dāng)cell重用較多時(shí),考慮內(nèi)存問(wèn)題,建議用刪除cell的所有子視圖方法(做視頻播放的時(shí)候).

4.cell做一個(gè)tag標(biāo)記,對(duì)cell將要展示的差異內(nèi)容進(jìn)行判斷

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
     cell.myLabel.text = [NSString stringWithFormat:@"我的Label%ld", indexPath.row];
      cell.tag = indexPath.row;
      if (cell.tag == 5) {
          cell.imageVIew.backgroundColor = [UIColor greenColor];
      }
      if (cell.tag != 5) {
          cell.imageVIew.backgroundColor = [UIColor whiteColor];
     }
     return cell;
 }

三 區(qū)分一下重用cell的兩個(gè)方法

//方法一
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

//方法二
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

在iOS文檔中對(duì)方法二有這樣的特殊描述:important


文檔截圖

不同之處:
1.方法二中總是返回一個(gè)有效的UITableViewCell
2.方法二的正確使用方法。這里解釋說(shuō)要先進(jìn)行注冊(cè)我們自定義或者通過(guò)nib的類和標(biāo)識(shí)符吱肌,然后再使用方法二進(jìn)行重用痘拆。所以現(xiàn)在我們崩潰的原因就已經(jīng)明確了,問(wèn)題就出在沒(méi)有進(jìn)行先注冊(cè)我們自定義的類和標(biāo)識(shí)符氮墨。(先注冊(cè),就不需要判空操作)

所以....以后使用可以如下

方法一:判空操作
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MeetingReplyBasicCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BasicCell"];
    if (!cell) {
        cell = [[MeetingReplyBasicCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BasicCell"];
    }
    
    return cell;
}

方法二:注冊(cè)操作
[self.tableView registerClass:[MeetingReplyBasicCell class] forCellReuseIdentifier:@"BasicCell"];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MeetingReplyBasicCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BasicCell" forIndexPath:indexPath];
    
    return cell;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纺蛆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子规揪,更是在濱河造成了極大的恐慌桥氏,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猛铅,死亡現(xiàn)場(chǎng)離奇詭異字支,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)奸忽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)堕伪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人栗菜,你說(shuō)我怎么就攤上這事欠雌。” “怎么了疙筹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵富俄,是天一觀的道長(zhǎng)禁炒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)霍比,這世上最難降的妖魔是什么幕袱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮悠瞬,結(jié)果婚禮上凹蜂,老公的妹妹穿的比我還像新娘。我一直安慰自己阁危,他們只是感情好玛痊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著狂打,像睡著了一般擂煞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上趴乡,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天对省,我揣著相機(jī)與錄音,去河邊找鬼晾捏。 笑死蒿涎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惦辛。 我是一名探鬼主播劳秋,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼胖齐!你這毒婦竟也來(lái)了玻淑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤呀伙,失蹤者是張志新(化名)和其女友劉穎补履,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體剿另,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡箫锤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雨女。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谚攒。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖戚篙,靈堂內(nèi)的尸體忽然破棺而出五鲫,到底是詐尸還是另有隱情溺职,我是刑警寧澤岔擂,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布位喂,位于F島的核電站,受9級(jí)特大地震影響乱灵,放射性物質(zhì)發(fā)生泄漏塑崖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一痛倚、第九天 我趴在偏房一處隱蔽的房頂上張望规婆。 院中可真熱鬧,春花似錦蝉稳、人聲如沸抒蚜。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗡髓。三九已至,卻和暖如春收津,著一層夾襖步出監(jiān)牢的瞬間饿这,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工撞秋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留长捧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓吻贿,卻偏偏與公主長(zhǎng)得像串结,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舅列,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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