面試的時候遇到這個問題,竟一時沒有全答上來,於是Google了一下,常見的一些譬如Cell重用
、設計統一Cell
、緩存Cell高度
,Cell數據資源緩存
,這些其實平時都在用,但因爲平時還是缺乏總結,回答這麼個問題的時候卻只想到說“==重用==”、“==緩存==”,道理你都懂,但這樣極度概括的答案在面試過程中並不是什麼好答案,深有體會~
另外,也有自己平時很少用而想不起來的,就是性能要求更高一些的話Cell中用到的視圖控件可以儘可能自行drawRect
。
面試結果也未可知,便先喫一塹長一智,趁熱將其總結總結。
Cell重用機制
這是TableView的基本使用,僅作簡單歸納。
[tableView dequeueReusableCellWithIdentifier:(NSString )identifier forIndexPath:(NSIndexPath )indexPath];
使用這個方法需要提前註冊Cell到對應的tableView:
- 1、Stroyboard: 定義Cell的Prototype,並設置其Reusable Identifier
這裏值得一提的是:Cell的Prototype最好高度抽象統一,越少越好,因爲每個不同的Prototype都有其對應的Cell重用池,創建的Cell就越多,重用效率也就越低。(詳見以下設計統一規格的Cell)
- 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
-
……
參考
知乎上有個討論,闡述了許多各種各樣不同的思路,雖然很少情況需要那麼極致,但也可以在必要的時候嘗試看看,不過相應的代碼量增加了,可一定要注意避免各種莫名bug出現哦~