UITableView的優(yōu)化(面試必備)

1. a.將cell及它的子控件設置為不透明的。b.盡量少用或不用透明圖層。c.減少子控件的數(shù)量。d.盡量少用addView給Cell動態(tài)添加View,可以初始化時就添加,然后通過hide來控制是否顯示。e如果Cell內(nèi)現(xiàn)實的內(nèi)容來自web,使用異步加載,緩存請求結果這個在我的《iOS多圖下載案例》系列文章中有具體講解原理,這個采用sdwebimage這個第三方框架即可。這幾個都是通過輕量級cell來對tableview進行優(yōu)化。

設置透明的話,處理器需要繪制渲染在cell下方的視圖或需要引用很多系統(tǒng)方面的東西,影響渲染速度。所以盡量設置其為不透明,提升渲染的速度??梢詫able cell及其子視圖的opaque屬性設為YES(默認值)。其中的特例包括背景色,它的alpha值應該為1(例如不要使用clearColor);圖像的alpha值也應該為1,或者在畫圖時設為不透明。渲染最慢的操作之一就是混合(blending)了。

當我們向cell添加大量添加控件時,對資源的開銷也會很大。這時候如果我們要優(yōu)化的話,可以在自定義的cell重寫drawrect方法,也可以寫個draw方法。這里是需要異步繪制,但如果在重寫drawRect方法就不需要用GCD異步線程了,因為drawRect本來就是異步繪制的。這我就不舉例子了,大家可以看看coretext。


2.正確使用reuseIdentifier來重用Cell。

UITableView只需要一屏幕的UITableViewCell對象即可。因此在cell不可見時,可以將其緩存起來,而在需要時繼續(xù)使用它即可。而UITableView也提供了這種機制,只需要簡單地設置一個identifier即可。

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

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

if(cell==nil) {

cell= [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault ?reuseIdentifier:@"cell"];

}

return cell;

}

3.提前計算并緩存好高度(布局),因為heightForRowAtIndexPath:是調(diào)用最頻繁的方法。

先舉個小實例:

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{

return10;

}

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

UITableViewCell*cell = [tableViewdequeueReusableCellWithIdentifier:@"cell"];

if(cell==nil) {

cell= [[UITableViewCellalloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:@"cell"];

}

returncell;

}

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

NSLog(@"%ld",(long)indexPath.row);

return100;

}

@end

當前屏幕顯示4個cell,總共5個cell。這里高度簡單設為100,如果你的應用需要做不等高cell,那么每次你都要重新計算高度,嚴重影響性能,我這里只是打印一下,給大家看看效果。

打印結果:


通過打印結果,雖然我們只有5個cell,屏幕顯示4個cell,但是heightforrow這個方法竟然執(zhí)行了5*5+4遍,如果我要顯示cell個數(shù)更多的話,將調(diào)用更多次這個方法。所以優(yōu)化tableview的一個思想就是把高度緩存起來,方便多次調(diào)用。所以我們寫個數(shù)組,將計算完的高度寫入數(shù)組,下次用的時候直接數(shù)組里取。

實際應用:

懶加載一個可變數(shù)組來存放高度:

- (NSMutableArray*)array{

if(!_array) {

_array= [NSMutableArrayarray];

}

return_array;

}

聲明一個變量height來存放高度,然后將高度放進可變數(shù)組里,放完后,這個方法就會從數(shù)組里取高度這樣你就不用計算高度。

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

CGFloatheight;

if(_array.count>indexPath.row) {

height =[[self.arrayobjectAtIndex:indexPath.row]floatValue];

}else{

Stautes*s =self.ary[indexPath.row];

height = s.cellHeight;

[self.arrayaddObject:[NSNumbernumberWithFloat:height]];

}

NSLog(@"%f---%lu",height,(unsignedlong)self.array.count);

returnheight;

}

我是在另一個類計算高度,主要是根據(jù)后臺傳的視頻文字來進行判斷然后設置高度:

#import"Stautes.h"

@implementationStautes

- (CGFloat)cellHeight

{

if(_cellHeight==0) {

CGFloatspace =10;

/**圖像*/

CGFloaticonX = space;

CGFloaticonY = space;

CGFloaticonWH =30;

self.iconFrame=CGRectMake(iconX, iconY, iconWH, iconWH);

/**昵稱*/

CGFloatnameX =CGRectGetMaxX(self.iconFrame) + space;

CGFloatnameY = iconY;

NSDictionary*nameAtt =@{NSFontAttributeName: [UIFontsystemFontOfSize:17]};

//計算昵稱文字的尺寸

CGSizenameSize = [self.namesizeWithAttributes:nameAtt];

CGFloatnameW = nameSize.width;

CGFloatnameH = nameSize.height;

self.nameFrame=CGRectMake(nameX, nameY, nameW, nameH);

/** vip */

if(self.isVip) {

CGFloatvipX =CGRectGetMaxX(self.nameFrame) + space;

CGFloatvipW =14;

CGFloatvipH = nameH;

CGFloatvipY = nameY;

self.vipFrame=CGRectMake(vipX, vipY, vipW, vipH);

}

/**正文*/

CGFloattextX = iconX;

CGFloattextY =CGRectGetMaxY(self.iconFrame) + space;

CGFloattextW = [UIScreenmainScreen].bounds.size.width-2* space;

NSDictionary*textAtt =@{NSFontAttributeName: [UIFontsystemFontOfSize:14]};

//最大寬度是textW,高度不限制

CGSizetextSize =CGSizeMake(textW,MAXFLOAT);

CGFloattextH = [self.textboundingRectWithSize:textSizeoptions:NSStringDrawingUsesLineFragmentOriginattributes:textAttcontext:nil].size.height;

self.textFrame=CGRectMake(textX, textY, textW, textH);

/**配圖*/

if(self.picture) {//有配圖

CGFloatpictureWH =100;

CGFloatpictureX = iconX;

CGFloatpictureY =CGRectGetMaxY(self.textFrame) + space;

self.pictureFrame=CGRectMake(pictureX, pictureY, pictureWH, pictureWH);

_cellHeight=CGRectGetMaxY(self.pictureFrame) + space;

}else{

_cellHeight=CGRectGetMaxY(self.textFrame) + space;

}

}

NSLog(@"計算");

return_cellHeight;

}

@end

打印結果如下:太長我就放一段,計算9次后就不再計算了,優(yōu)化了tableview。


4.滑動的UITableView時,按需加載對應的內(nèi)容

//按需加載 - 如果目標行與當前行相差超過指定行數(shù),只在目標滾動范圍的前后指定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+33)?{

[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];

}

}

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容