UITableView的優化

UITableView無疑是iOS開發中最重要的控件,它的優化直接牽扯到性能和體驗,雖然所有優化的基礎核心思想都大同小異,但博客魚龍混雜眾說紛紜,各類技巧也是層出不窮看起來都很有道理,于是決定按照自己的理解全面總結一下,便于記憶和重溫。

最基礎的Cell復用

dequeueReusableCellWithIdentifier,通過Identifier復用。給UITableView添加拓展方法簡化cell的復用方法。如下:

- (UITableViewCell*)loadXibCellWithIdentifier:(NSString*)cellIdentifier {

? ? ? ?UITableViewCell* cell = [self dequeueReusableCellWithIdentifier:cellIdentifier];

? ? ? ?if (nil == cell) { ?

? ? ? ? ? ? UINib *nib = [UINib nibWithNibName:cellIdentifier bundle:nil];

? ? ? ? ? ? [self registerNib:nib forCellReuseIdentifier:cellIdentifier];

? ? ? ? ? ? cell = [self dequeueReusableCellWithIdentifier:cellIdentifier];

? ? ? ? }

? ? ? ? return cell;

}

算高

由于算高函數heightForRowAtIndexPath是代理中調用超級頻繁的函數,所以,提前算高,并將高度緩存在數據源中是很有必要的。而在iOS8以上提供了設置estimatedRowHeight估算高度后根據cell的自動布局自動高度的方法雖然極度方便(甚至不用實現高度回調函數),但其性能卻不容樂觀,特別是由于xib的加載是首次加載便全控件加載。

但是如果你的項目已經使用了sb或xib,UITableView+FDTemplateLayoutCell從run loop的角度提供了很優秀的解決方案。

圖片緩存

圖片大多使用SDWebImage所以圖片的內存緩存和硬盤緩存都是默認完成的。

富文本和圓角

兩個不可觸碰的禁區,代價極其昂貴。

子控件和繪制

subviews自然是越少越好,而且要盡量不透明(即Color Blended Layer選中后的紅色區域越少越好)。當遭遇復雜頁面的性能瓶頸,用drawRect或其他方法實現控件的全面異步繪制是很好的選擇,但這就要求舍棄xib和storyboard,而且布局方面也變得不是十分方便了。

UIGraphicsBeginImageContextWithOptions(rect.size,YES,0); ?//創建基于位圖的上下文

CGContextRefcontext =UIGraphicsGetCurrentContext(); ?//獲取上下文

[[UIColorcolorWithRed:250/255.0green:250/255.0blue:250/255.0alpha:1]set]; ?//背景色設置

CGContextFillRect(context, rect); ?//背景色填充

[testString drawInContext:context withPosition:CGPointMake(x, y) andFont:font andTextColor:color andHeight:rect.size.height]; ?//簡單文字繪制

[testImage drawInRect:CGRectMake(x, y, w, h) blendMode:kCGBlendModeNormal alpha:alpha]; ?//簡單圖片繪制

最變態的VVeboTableViewDemo

來自于github上一個2k+star的demo,其核心優化思想是:1、異步將內容渲染成圖片;2、依照滑動速度,按需加載滾動目標位置前后指定三行的cell。

解讀與記錄

首先是算高。當獲取到數據源之后,應根據數據源和視圖布局規則計算出整個cell的frame,用于繪制時的大背景和heightForRowAtIndexPath函數;計算其他可變高度(如textframe)。

然后需要分解cell的布局,基本固定的控件和內容應繪制在一張圖片中(如昵稱,時間,點贊數等元素),主要使用[string/image drawInRect]的繪制方法(demo中的富文本繪制使用了極度復雜的drawInContext擴展方法,可能是為了兼容iOS8以下)。

而特殊的控件則需要單獨處理,如頭像(使用白邊的中心鏤空的蒙版,解決圓角問題),如附圖(scrollview),內容(未使用Label,使用以View為基類封裝了繪制方法的自定義控件VVeboLabel,具有顏色字體行間距對齊方式等功能,還提供了超鏈接點擊事件(但實現方式過于變態)。

而cell暴露給tableview的屬性有數據源字典/模型,接口有draw,clear,releaseMemory(移除時候使用),cellForRowAtIndexPath函數中先調用cell的clear,再賦值data和draw。

最后,依照滾動速度按需加載。scrollViewWillEndDragging委托函數中,根據targetContentOffset和velocity判斷需要跳過和需要加載的row,存入needLoadArr用于加載。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容