關(guān)于表格視圖UITableView的流暢度優(yōu)化小結(jié)

UITableView的優(yōu)化小結(jié)

UITableView在ios的實(shí)際開(kāi)發(fā)中使用頻次有多重不用多說(shuō)家卖,而它的優(yōu)化技巧既是難點(diǎn)也是必須掌握的要點(diǎn)眨层;作為一個(gè)在UITableView的優(yōu)化路上還沒(méi)走多遠(yuǎn)的初學(xué)者,最近在網(wǎng)上到處找了蠻多相關(guān)資料來(lái)閱讀上荡,自己也結(jié)合自己的項(xiàng)目做了一些思索和實(shí)踐趴樱,讓我們一起來(lái)學(xué)習(xí)吧!如果你在這方面已經(jīng)有了一些心得酪捡,鄭重推薦一個(gè)開(kāi)源項(xiàng)目VVeboTableViewDemo,值得學(xué)習(xí)叁征!

UITableView的核心簡(jiǎn)介

  • UITableView的核心思想就是對(duì)UITableViewCell的重用,大概原理就是:UITableView剛開(kāi)始只會(huì)創(chuàng)建一個(gè)屏幕或者一個(gè)屏幕多一點(diǎn)的UITableViewCell逛薇,當(dāng)UITableView滑動(dòng)的時(shí)候捺疼,滑出屏幕的UITableViewCell會(huì)被放到重用池中等待重用,而由于滑動(dòng)將在屏幕上出現(xiàn)新的UITableViewCell金刁,這些UITableViewCell首先是去重用池中取帅涂,取不到再去創(chuàng)建新的;這樣做的好處就是尤蛮,你的UITableView從始至終都只會(huì)創(chuàng)建一個(gè)屏幕的UITableViewCell,而不會(huì)由于你的tableview有幾百行cell就去創(chuàng)建幾百個(gè)cell斯议。
  • 要對(duì)UITableView進(jìn)行優(yōu)化产捞,主要的代碼將放在以下兩個(gè)UITableView的代理方法中:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

那么在實(shí)際開(kāi)發(fā)中,在我們創(chuàng)建好UITableView后哼御,首先多次調(diào)用heightForRowAtIndexPath的方法從而確定UITableView的contentSize和cell的位置坯临,然后調(diào)用cellForRowAtIndexPath創(chuàng)建cell焊唬,并顯示在屏幕上;優(yōu)化的部分就集中在以上兩個(gè)方法中看靠。

1.0 原始代碼
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    BTNewsFlashCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NEWSCELL" forIndexPath:indexPath];
    BTNewsFlashModel *model = _dataArray[indexPath.row];
    cell.model = model;
    return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    BTNewsFlashModel *model = _dataArray[indexPath.row];
    NSInteger height = model.APicHeight;
    return height*WIDTH/model.APicWidth;
}

在這段代碼中第一個(gè)方法起到為cell賦值(model)的作用赶促,第二個(gè)方法起到根據(jù)數(shù)據(jù)源動(dòng)態(tài)計(jì)算行高的方法。問(wèn)題就處在第二個(gè)方法中挟炬,如果我們要?jiǎng)?chuàng)建100個(gè)cell甚至更多鸥滨,就會(huì)去計(jì)算100次,而且每當(dāng)你滾動(dòng)cell的時(shí)候還會(huì)去計(jì)算谤祖,這就很耗費(fèi)資源婿滓,甚至如果你的cell排布很復(fù)雜,那計(jì)算量就很可怕了粥喜。凸主。。oh额湘,怎么破????

1.1 優(yōu)化

我們?cè)趶木W(wǎng)上獲取到數(shù)據(jù)后卿吐,就立馬根據(jù)數(shù)據(jù)計(jì)算cell的高度,并為model添加cellHeight的屬性(保存cell的高度)锋华,在heightForRowAtIndexPath的方法中直接取來(lái)用就好了,不用每次去計(jì)算了嗡官。。哈哈 這樣會(huì)不會(huì)流暢一點(diǎn)呢供置,事實(shí)證明是的????谨湘,代碼如下

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    BTNewsFlashModel *model = _dataArray[indexPath.row];
    return model.cellHeight;
}

在這里,強(qiáng)烈推薦一個(gè)好用的第三方UITableView+FDTemplateLayoutCell,只需一句代碼芥丧,完美紧阔、perfect、100分

#import "UITableView+FDTemplateLayoutCell.h"

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [tableView fd_heightForCellWithIdentifier:@"reuse identifer" configuration:^(id cell) {
        // Configure this cell with data, same as what you've done in "-tableView:cellForRowAtIndexPath:"
        // Like:
        //    cell.entity = self.feedEntities[indexPath.row];
    }];
}
優(yōu)化 1.2

根據(jù)蘋果的描述续担,UIKit是我們最容易也是最常接觸到的框架擅耽,而我們使用
add subView添加控件都由UIKit完成,但是UIKit本質(zhì)上依賴于Core Graphics框架物遇,也是基于Core Graphics框架實(shí)現(xiàn)的乖仇。所以如果想要完成某些更底層的功能或者追求極致的性能,那么推薦使用Core Graphics完成询兴。如下一部分代碼:(完整代碼見(jiàn)VVeboTableViewDemo)

- (void)draw{
    if (drawed) {
        return;
    }
    NSInteger flag = drawColorFlag;
    drawed = YES;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        CGRect rect = [_data[@"frame"] CGRectValue];
        UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        [[UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1] set];
        CGContextFillRect(context, rect);
        
        if ([_data valueForKey:@"subData"]) {
            [[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1] set];
            CGRect subFrame = [_data[@"subData"][@"frame"] CGRectValue];
            CGContextFillRect(context, subFrame);
            [[UIColor colorWithRed:200/255.0 green:200/255.0 blue:200/255.0 alpha:1] set];
            CGContextFillRect(context, CGRectMake(0, subFrame.origin.y, rect.size.width, .5));
        }
 UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        dispatch_async(dispatch_get_main_queue(), ^{
            if (flag==drawColorFlag) {
                postBGView.frame = rect;
                postBGView.image = nil;
                postBGView.image = temp;
            }
        });
    });
    [self drawText];
    [self loadThumb];
}

優(yōu)化1.3

//按需加載 - 如果目標(biāo)行與當(dāng)前行相差超過(guò)指定行數(shù)乃沙,只在目標(biāo)滾動(dòng)范圍的前后指定3行加載。
 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ 

      NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)]; 
      NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject];  
      NSInteger skipCount = 8;
     if (labs(cip.row-ip.row)>skipCount) { 
          NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)]; 
         NSMutableArray *arr = [NSMutableArray arrayWithArray:temp]; 
         if (velocity.y<0) {
              NSIndexPath *indexPath = [temp lastObject];
              if (indexPath.row+3<datas.count) {
                      [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+1 inSection:0]]; 
                      [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+2 inSection:0]]; 
                      [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+3 inSection:0]];
                }
          } else { 
          NSIndexPath *indexPath = [temp firstObject]; 
          if (indexPath.row>3) { 
              [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-3 inSection:0]]; 
              [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-2 inSection:0]]; 
              [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:0]]; 
           }
     }
    [needLoadArr addObjectsFromArray:arr]; 
   }
}

記得在tableView:cellForRowAtIndexPath:方法中加入判斷:
(如果cell不在加載的范圍內(nèi)诗舰,就清除掉cell上面的子控件)

if (needLoadArr.count>0&&[needLoadArr indexOfObject:indexPath]==NSNotFound) {
    [cell clear]; 
    return;
  }

滾動(dòng)速度比較快的時(shí)候警儒,只加載一定范圍內(nèi)的cell,不會(huì)一次性加載太多,按需加載蜀铲,可以有效提高流暢度边琉。

總之,優(yōu)化tableView的流暢度就從三個(gè)方面著手

  1. 單獨(dú)計(jì)算cell的高度记劝,并保存下來(lái)
  2. 自己使用核心繪圖Core Graphics繪制cell上面的子視圖
  3. 按需加載cell
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蹄衷,隨后出現(xiàn)的幾起案子忧额,更是在濱河造成了極大的恐慌,老刑警劉巖愧口,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件睦番,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡耍属,警方通過(guò)查閱死者的電腦和手機(jī)托嚣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厚骗,“玉大人示启,你說(shuō)我怎么就攤上這事×旖ⅲ” “怎么了夫嗓?”我有些...
    開(kāi)封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)冲秽。 經(jīng)常有香客問(wèn)我舍咖,道長(zhǎng),這世上最難降的妖魔是什么锉桑? 我笑而不...
    開(kāi)封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任排霉,我火速辦了婚禮,結(jié)果婚禮上民轴,老公的妹妹穿的比我還像新娘攻柠。我一直安慰自己,他們只是感情好后裸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布瑰钮。 她就那樣靜靜地躺著,像睡著了一般微驶。 火紅的嫁衣襯著肌膚如雪飞涂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天祈搜,我揣著相機(jī)與錄音较店,去河邊找鬼。 笑死容燕,一個(gè)胖子當(dāng)著我的面吹牛梁呈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蘸秘,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼官卡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了醋虏?” 一聲冷哼從身側(cè)響起寻咒,我...
    開(kāi)封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颈嚼,沒(méi)想到半個(gè)月后毛秘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阻课,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年叫挟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片限煞。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抹恳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出署驻,到底是詐尸還是另有隱情奋献,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布旺上,位于F島的核電站瓶蚂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抚官。R本人自食惡果不足惜扬跋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凌节。 院中可真熱鬧钦听,春花似錦、人聲如沸倍奢。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)卒煞。三九已至痪宰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衣撬。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工乖订, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人具练。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓乍构,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親扛点。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哥遮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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