1.cell的重用
2.dequeueReusableCellWithIdentifier:forIndexPath:(會調用heightForRowAtIndexPath)和dequeueReusableCellWithIdentifier (后面這個不會再次調用heightForRowAtIndexPath)
2.1 tableView在cell顯示之前會調用heightForRowAtIndexPath,有多少個cell就會調用多少次,算contentSize
2.2使用了預估行高,并不會在顯示之前去計算獲取所有的行高(預估行高,等cell要顯示的時候才回去計算真實的高度),根據預估行高和實際行高來獲取cell的行高,先根據預估行高計算好要先獲取幾個cell,如果計算的這幾個cell高度確實夠(高度能超出屏幕的高度就不計算了.如果不夠還會計算),目的也是讓contentSize大于屏幕,就能滾動,后面要顯示,才來計算行高,所以會發現滾動條會跳
3.cell的高度是根據內容變化的時候,只計算一次,將高度緩存起來
overridefunctableView(tableView:UITableView, heightForRowAtIndexPath indexPath:NSIndexPath) ->CGFloat{
//獲取模型
letstatus =self.statuses![indexPath.row]
//判斷模型里面之前有沒有緩存過行高
ifstatus.rowHeight!=nil
{
//之前保存過行高,直接返回行高
returnstatus.rowHeight!
}
//自己計算行高:AutoLayout自動約束
//讓cell設置對應內容,可以直接直接獲取,這個cell不參與顯示
letcell = tableView.dequeueReusableCellWithIdentifier(ReuseIndentifier)as!HMStatusCell
cell.status= status
letheight = cell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
status.rowHeight= height
returnheight
}
4.下載圖片使用SDWebImage(異步操作)
5.cellForRowAtIndexPath不要做耗時操作
1.讀取文件,寫入文件,最好是放到子線程,或先讀取好,在讓tableView去顯示
2.盡量不要再這個方法里解壓資源
3.盡量少得計算計算,最好是先計算好,cellForRowAtIndexPath只做顯示
4.盡量不要去添加和移除view,現將會用到的控件懶加載,要就顯示,不要就隱藏
6.tableView滾動的時候,不要去做動畫(微信的聊天界面做的就很好,在滾動的時候,動態圖就不讓他動,滾動停止的時候才動,不然可能會有點影響流暢度)
7.cell里面的控件,約束最好不要使用remake,動態添加約束是比較耗性能的
8.cell里面的控件,背景最好是不透明的(圖層混合靠GPU去渲染,會影響性能,綠色的好,紅色的性能差), view的背景顏色clearColor盡量少
9.圖片圓角不要使用layer.cornerRadius,因為通過圖層去渲染的話都會影響性能
10.圖層最好不要使用陰影,陰影會導致離屏渲染(在進入屏幕渲染之前,還看不到的時候會再渲染一次,盡量不要產生離屏渲染)
11.異步繪制
12.柵格化
13.借助工具來測試性能
14.AsyncDisplayKit ->不使用UIKit (UIView) ->? (Node)
總結:
設置統一規格的Cell, 其子控件的顯示隱藏可以根據模型中不同的數據在代碼里面動態控制就好;在iOS中,系統是先調用“tableView:heightForRowAtIndexPath:”獲取每個Cell即將顯示的高度,確定整個UITableView的布局。然后才調用“tableView:cellForRowAtIndexPath”獲取Cell。因此,使用了ViewModel來保存UI信息,Cell高度的計算和使用的時機需要特別留意。
提前處理Cell需要顯示的數據資源;在Cell顯示之前,將從服務器加載獲取到的原始數據在ViewModel中進行提前處理,一般包括圖片的加載和壓縮、富文本的多樣化顯示(NSString->NSAttributeString)。
另外還有些更為極致的一些方式和操作細節也就不深入展開了,大致整合一下。
Cell中的view盡可能不要使用透明
減少子視圖的層級關系
圖片載入在后臺進程進行,滾出可視范圍的載入進程cancel掉
圖片資源盡可能使用PNG
2.圖片異步下載,異步解碼,緩存解碼結果。
6.不要繪制圓角、陰影,盡量用圖片來替換。總之一句話,能異步不要同步,能用gpu不要用cpu。
用 “空間換時間”
將計算行高的時間提前到從服務器摟回數據的時候,計算完了高度一并寫回數據庫,別告訴我你在主線程里阻塞式的處理網絡請求。。。。面壁思過去吧,別浪費了 GCD,NSOperationQueue的青春。最先想到的還是 NSThread 的同學,證明你已經老了。。。現在幾乎大部分的多線程操作都不需要用到 NSThread 和 runloop了。
調試應用性能一定要用真機,Mac 的性能完爆 iPhone,所有不要說我的應用在模擬器上調試時不卡啊!模擬器只能模擬 iOS 軟件的運行環境,不能模擬硬件性能!
UITableView性能優化-一次面試后的反思總結
面試的時候遇到這個問題,竟一時沒有全答上來,于是Google了一下,常見的一些譬如Cell重用、設計統一Cell、緩存Cell高度,Cell數據資源緩存,這些其實平時都在用,但因為平時還是缺乏總結,回答這么個問題的時候卻只想到說“==重用==”、“==緩存==”,道理你都懂,但這樣極度概括的答案在面試過程中并不是什么好答案,深有體會~
另外,也有自己平時很少用而想不起來的,就是性能要求更高一些的話Cell中用到的視圖控件可以盡可能自行drawRect。
面試結果也未可知,便先吃一塹長一智,趁熱將其總結總結。
Cell重用機制
這是TableView的基本使用,僅作簡單歸納。
[tableView dequeueReusableCellWithIdentifier:(NSString)identifier forIndexPath:(NSIndexPath)indexPath];
使用這個方法需要提前注冊Cell到對應的tableView:
1、Stroyboard: 定義Cell的Prototype,并設置其Reusable Identifier
2、Xib自定義:
[registerNib:(nullable UINib)nib forCellReuseIdentifier:(NSString)identifier];
3、代碼自定義:
[registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier];
設計統一規格的Cell
統一Cell的規格,不僅能減少設計不同Cell所需要代碼量和nib文件,更重要的是能提高Cell的重用率,提升TableView整體性能。
等高的Cell好設計,顯示不同數據就可以了,無須多費篇幅。
動態計算高度的Cell也應該統一設計,比如下面這個赤兔的例子
創建ViewModel,計算并儲存Cell的UI尺寸信息
@interface BYTweetViewModel : NSObject
@property(strong, nonatomic) BYTweetModel *dataModel; //原始數據模型
@property(assign, nonatomic) CGFloat cellHeight; //Cell 高度
(void)calculateCellHeight; //計算高度
@end
這里有個坑需要注意:
在iOS中,系統是先調用“tableView:heightForRowAtIndexPath:”獲取每個Cell即將顯示的高度,確定整個UITableView的布局。然后才調用“tableView:cellForRowAtIndexPath”獲取Cell。因此,使用了ViewModel來保存UI信息,Cell高度的計算和使用的時機需要特別留意。
提前處理Cell需要顯示的數據資源
在Cell顯示之前,將從服務器加載獲取到的原始數據在ViewModel中進行提前處理,一般包括圖片的加載和壓縮、富文本的多樣化顯示(NSString->NSAttributeString)。
這時ViewModel可能會是這樣
@interface BYTweetViewModel : NSObject
@property(strong, nonatomic) BYTweetModel *dataModel; //原始數據模型
@property(assign, nonatomic) CGFloat cellHeight; //Cell 高度
//需要顯示的數據內容
@property(strong, nonatomic) NSAttributeString *titleToShow;
@property(strong, nonatomic) NSAttributeString *contentToShow;
(void)calculateCellHeight; //計算高度
(void)handleSourceDataModel;
@end
其它
我了解的,也是常用的方案基本是以上幾種了,總之呢,還是可以回到我面試時候的高度概括,盡可能“重用”、“緩存”,用空間換取時間。
另外還有些更為極致的一些方式和操作細節也就不深入展開了,大致整合一下。
Cell中的view盡可能不要使用透明
減少子視圖的層級關系
圖片載入在后臺進程進行,滾出可視范圍的載入進程cancel掉
圖片資源盡可能使用PNG
……