使用自動(dòng)布局的cell自適應(yīng)高度和簡(jiǎn)單的性能優(yōu)化

? 在iOS的開(kāi)發(fā)過(guò)程中,UITableView的使用頻次是非常高的,用來(lái)加載具有一定規(guī)則的的cell來(lái)呈現(xiàn)更多的展示內(nèi)容.而根據(jù)規(guī)則的不同我們也要對(duì)cell做出相應(yīng)的改變--自定義cell.使用自定義cell就不得不說(shuō)一下cell的高度計(jì)算.

在iOS6以前

手機(jī)坐標(biāo)寬度為固定的320,cell內(nèi)部的布局基本都是依靠setFrame方法.也就是說(shuō)cell的橫向布局基本都是固定的(有的可能在橫向也會(huì)做出改變,但這些都可以提前計(jì)算出寬度).

- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

introw?=?[indexPath?row];

//?列寬

CGFloat?contentWidth?=?self.tv.frame.size.width;

//?用何種字體進(jìn)行顯示

UIFont?*font?=?[UIFont?systemFontOfSize:14];

//?該行要顯示的內(nèi)容

NSString?*content?=?[_arr?objectAtIndex:row];

//?計(jì)算出顯示完內(nèi)容需要的最小尺寸

CGSize?size?=?[content?sizeWithFont:font?constrainedToSize:CGSizeMake(contentWidth,?1000.0f)?lineBreakMode:UILineBreakModeWordWrap];

//?這裏返回需要的高度

returnsize.height+20;

}

使用這種方法,乍看是沒(méi)什么問(wèn)題的,但是我們知道每次reloadData的時(shí)候都會(huì)先走這個(gè)代理方法來(lái)計(jì)算所有cell的高度.也就是說(shuō)如果tableView中有100個(gè)cell的話,它會(huì)先走100次,然后在滑動(dòng)tableView讓cell出現(xiàn)的時(shí)候會(huì)在計(jì)算一次.這意味著每次tableView在顯示之前都要在主線程做出大量的計(jì)算.如果cell做的比較復(fù)雜可能還會(huì)出現(xiàn)滑動(dòng)卡頓的情況.一般碰到這種情況,我們會(huì)在得到數(shù)據(jù)源的同時(shí)通過(guò)sizeWithFont:constrainedToSizelineBreakMode:方法來(lái)得到高度,并將高度保存在數(shù)組中.

如果cell比較復(fù)雜,造成滑動(dòng)卡頓,那我們就得從cell本身下手了(產(chǎn)品經(jīng)理,你的需求臣妾做不到啊):

1,復(fù)用cell.這個(gè)應(yīng)該不用多說(shuō)了吧.另外xib寫(xiě)的cell可以在右邊直接注冊(cè)復(fù)用標(biāo)識(shí)符的.

cell Indentifier

2,減少視圖的數(shù)目.view是是一個(gè)很大的對(duì)象,創(chuàng)建它需要消耗很大的資源并且影響渲染速度.所以還是多使用屬性字符串來(lái)減少視圖的數(shù)量.如果你們的產(chǎn)品對(duì)滑動(dòng)要求很苛刻,而你又恰好有大量的時(shí)間的話,可以考慮drawRect

- (void)drawRect:(CGRect)rect { if (image) { [image drawAtPoint:imagePoint]; self.image = nil; } else { [placeHolder drawAtPoint:imagePoint]; } [text drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeTailTruncation]; }

這樣確實(shí)能很大程度的提高流暢度,但是會(huì)給開(kāi)發(fā)和維護(hù)造成很大的難度.

3,不要阻塞主線程.不要再滑動(dòng)的時(shí)候讓主線程執(zhí)行耗時(shí)的方法,如圖片請(qǐng)求.

其實(shí)主要的方法就這幾個(gè),之前百度了幾篇文章,講的很細(xì),但是在巨大多數(shù)開(kāi)發(fā)過(guò)程中真正會(huì)用到的也就這幾種.

iOS6之后

iOS6之后蘋(píng)果引入了自動(dòng)布局(主要針對(duì)不同屏幕寬度做適配),我們也將cell的布局從setFrame方法變?yōu)榱颂砑蛹s束,在配合x(chóng)ib的使用也極大的提高了開(kāi)發(fā)速度.在很長(zhǎng)一段時(shí)間里,我是不大喜歡用xib+autoLayout來(lái)開(kāi)發(fā)的,因?yàn)楫?dāng)時(shí)會(huì)覺(jué)得,xib寫(xiě)的cell的可變動(dòng)性太小了,而且高度也不大好計(jì)算.但是在后來(lái)的開(kāi)發(fā)和學(xué)習(xí)后,我基本寫(xiě)cell都會(huì)使用xib加約束.

iOS6之后,引入了一個(gè)新的方法來(lái)計(jì)算cell的高度

- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize;

首先,創(chuàng)建一個(gè)UITableViewCell的子類,在cell上添加視圖,然后給視圖添加各種約束.注意添加約束的時(shí)候一定要有上下關(guān)聯(lián)(也就是說(shuō)最上的視圖對(duì)contentView有top約束,最下的視圖對(duì)contentView有bottom的約束,兩個(gè)視圖就要有直接或者間接的縱向約束).然后按照如下方法就能得到高度.

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;

{

EpListCell*cell = (EpListCell*)[selftableView:_tableViewcellForRowAtIndexPath:indexPath];

[cellsetNeedsUpdateConstraints];

[cellupdateConstraintsIfNeeded];

CGSizesize = [cell.contentViewsystemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

returnsize.height+1.0f;//contenView高度和cell高度相差1

}

當(dāng)你嘗試這種方法的時(shí)候,你會(huì)發(fā)現(xiàn)為什么我設(shè)置numberOfLines=0并且字?jǐn)?shù)明顯超過(guò)了一行,它為什么不換行.這時(shí)候你只用給需要換行的label加上preferredMaxLayoutWidth就好了.

self.medicineNameLabel.preferredMaxLayoutWidth=SCREEN_WIDTH-60;

這樣他就能正常換行并且自動(dòng)計(jì)算高度了.

但是這樣你依舊會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,就是在得到數(shù)據(jù)源同時(shí)來(lái)計(jì)算cell的高度變麻煩了.我必須創(chuàng)建一個(gè)專門(mén)計(jì)算高度的cell來(lái)計(jì)算高度.

然而iOS7用給我們帶來(lái)了一個(gè)新的方法.

- (CGFloat)tableView:(UITableView*)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath*)indexPath

如果實(shí)現(xiàn)了這個(gè)代理方法,那么在tableView reloadData時(shí)將不在一次性執(zhí)行100次cell高度的計(jì)算方法,而是將上面這個(gè)代理方法返回的值作為cell的預(yù)估高度.如果cell比較少,且預(yù)估高度和實(shí)際高度相差比較大的情況下滑動(dòng)tableView,你會(huì)發(fā)現(xiàn)滾動(dòng)條在跳動(dòng).

總覺(jué)得這個(gè)方法有點(diǎn)得不償失,提高刷新速度的同時(shí),反而降低了滑動(dòng)的流暢程度.

iOS8之后,蘋(píng)果對(duì)這個(gè)方法做了改進(jìn).如果你的cell中的約束符合規(guī)范

在寫(xiě)了

- (CGFloat)tableView:(UITableView*)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath*)indexPath

方法后,可以不用寫(xiě)

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath

而且滑動(dòng)效率也有所提高.

UITableView作為iOS開(kāi)發(fā)中最重要的一個(gè)控件,蘋(píng)果也不停的在對(duì)其作出更多的優(yōu)化.值得慶幸的是,適配并不麻煩.否則真的是嗶了狗了...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,673評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,610評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,939評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,668評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,004評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,173評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,705評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,426評(píng)論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,656評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,833評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,247評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,580評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,371評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,621評(píng)論 2 380

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