一. Cell重?用
1. 數(shù)據(jù)源?方法優(yōu)化
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath;
在可?的??會重復繪制??考阱,每次刷新顯示都會去創(chuàng)建新的Cell鞠苟,非常耗費性能乞榨。
解決?案:
?先創(chuàng)建?個靜態(tài)變量reuseID(代理方法返回Cell會調?用很多次当娱,防?重復創(chuàng)建,static保證只會被創(chuàng)建?次态秧,提?性能)扼鞋,然后申鱼,從緩存池中取相應 identifier的Cell并更新數(shù)據(jù),如果沒有淫半,才開始alloc新的Cell,并用identifier標識 Cell科吭。每個Cell都會注冊?個identifier(重用標識符)放?入緩存池猴鲫,當需要調?的時候就直接從緩存池里找對應的id对人,當不需要時就放入緩存池等待調?拂共。(移出屏幕的 Cell才會放?入緩存池中,并不不會被release)所以在數(shù)據(jù)源?法中做出如下
優(yōu)化:
staticNSString*reuseID = “reuseCellID”;// 緩存池中取已經創(chuàng)建的cellUITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:reuseID];
2. 緩存池的實現(xiàn)
當Cell要alloc時势告,UITableView會在堆中開辟?一段內存以供Cell緩存之?用抚恒。Cell的重 ?用通過identifier標識不同類型的Cell咱台,由此可以推斷出俭驮,緩存池外層可能是?個可變字典,通過key來取出內部的Cell混萝,?而緩存池為存儲不同高度、不同類型(包含圖片、 Label等)的Cell雄坪,可以推斷出緩存池的字典內部可能是一個可變數(shù)組,用來存放不不同 類型的Cell维哈,緩存池中只會保存已經被移出屏幕的不同類型的Cell。
3. 緩存池獲取可重用Cell兩個?法的區(qū)別
-(nullable__kindofUITableViewCell*)dequeueReusableCellWithIdentifier: (NSString*)identifier;這個?法會查詢可重?用Cell飘庄,如果注冊了原型Cell购撼,能夠查詢到跪削,否則,返回nil;?且需要判斷if(cell ==nil)晃跺,才會創(chuàng)建Cell毫玖,不推薦-(__kindofUITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier forIndexPath:(NSIndexPath*)indexPathNS_AVAILABLE_IOS(6_0);使?這個?法之前掀虎,必須通過xib(storyboard)或是Class(純代碼)注冊可重?用 Cell付枫,?而且這個方法?定會返回一個Cell//注冊Cell- (void)registerNib:(nullableUINib*)nib forCellReuseIdentifier:(NSString*)identifierNS_AVAILABLE_IOS(5_0);- (void)registerClass:(nullableClass)cellClass forCellReuseIdentifier:(NSString*)identifierNS_AVAILABLE_IOS(6_0);
好處:
如果緩沖區(qū) Cell 不存在,會使用原型 Cell 實例例化?個新的 Cell二打,不需要再判 斷,同時代碼結構更清晰址儒。
二. 定義?種(盡量少)類型的Cell及善?hidden隱藏(顯示)subviews
1. ?種類型的Cell
分析Cell結構衅疙,盡可能的將 相同內容的抽取到?種樣式Cell中,前?面已經提到了了
Cell的重?機制饱溢,這樣就能保證UITbaleView要顯示多少內容,真正創(chuàng)建出的Cell可能 只比屏幕顯示的Cell多?點绩郎。雖然Cell的’體積’可能會大點,但是因為Cell的數(shù)量量不會很多溉仑,完全可以接受的。
好處:
減少代碼量量浊竟,減少Nib?件的數(shù)量津畸,統(tǒng)?一個Nib?文件定義Cell振定,容易修改肉拓、維護
基于Cell的重?用,真正運?時鋪滿屏幕所需的Cell數(shù)量?致是固定的暖途,設為N個膏执。所 以如果如果只有一種Cell残揉,那就是只有N個Cell的實例;但是如果有M種Cell,那么運行時最多可能會是“M x N = MN”個Cell的實例例抱环,雖然可能并不會占?用太多內存,但是能少點不是更好嗎眶痰。
2. 善用hidden隱藏(顯示)subviews
只定義?種Cell梯啤,那該如何顯示不同類型的內容呢?
答案就是竖伯,把所有不同類型的 view都定義好因宇,放在cell??,通過hidden顯示察滑、隱藏,來顯示不同類型的內容户盯。畢竟饲化,在?戶快速滑動中莽鸭,只是單純的顯示吃靠、隱藏subview比實時創(chuàng)建要快得多。
三. 提前計算并緩存Cell的?高度
在iOS中礁阁,不設UITableViewCell的預估行高的情況下,會優(yōu)先調用 ”tableView:heightForRowAtIndexPath:”?法,獲取每個Cell的即將顯示的高度裂逐, 從而確定UITableView的布局,實際就是要獲取contentSize(UITableView繼承?UIScrollView,只有獲取滾動區(qū)域卜高,才能實現(xiàn)滾動),然后才調用”tableView:cellForRowAtIndexPath”,獲取每個Cell南片,進?賦值庭敦。如果項?中模塊有 10000個Cell需要顯示,可想?知...
解決?案:
我個?認為秧廉,可以創(chuàng)建?個frame模型,提前計算每個Cell的?高度嚼锄。參考其中一篇博客的時候蔽豺,在解決這個問題的時候区丑,可以將計算Cell的?高度放?入數(shù)據(jù)模 型修陡,但這與MVC設計模式可能稍微有點沖突,這個時候我就想到MVVM這種設計模式宴杀,這個時候才能稍微有點MVVM這種設計模式的優(yōu)點(其實還是很不理理解的),可 以講計算Cell?高度放入ViewModel(視圖模型)中婴氮,讓Model(數(shù)據(jù)模型)只負責處理數(shù)據(jù)盾致。
四.異步繪制(自定義Cell繪制)
遇到?較復雜的界?面的時候,如復雜點的圖文混排庭惜,上?的那種優(yōu)化行高的?式可
能就不能滿?要求了,當然了护赊,由于我的開發(fā)經驗尚短,說實話节吮,還沒遇到要將?定義的Cell重新繪制
五.滑動時判耕,按需加載
開發(fā)的過程中自定義Cell的種類千奇百怪透绩,但Cell本來就是?來顯示數(shù)據(jù)的,不說100%帶有圖片碳竟,也差不多,這個時候就要考慮莹桅,下滑的過程中可能會有點卡頓烛亦,尤其網絡不好的時候,異步加載圖片是個程序員都會想到此洲,但是如果給每個循環(huán)對象都加上異步加載,開啟的線程太多呜师,?樣會卡頓,我記得好像線程條數(shù)?般3-5條衷畦,最多也就6條吧。這個時候利利?用UIScrollViewDelegate兩個代理方法就能很好地解決這個問題祈争。
- (void)scrollViewDidEndDragging:(UIScrollView*)scrollView willDecelerate: (BOOL)decelerate- (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView
六.緩存View
當Cell中的部分View是?常獨立的角寸,并且不便于重?的,而且“體積”?常小扁藕,在內存可控的前提下,我們完全可以將這些view緩存起來亿柑。當然也是緩存在模型中。
七.避免?量的圖片縮放疟游、顏?漸變等,盡量顯示“大?剛好合適的圖片資源”
八.避免同步的從網絡颁虐、文件獲取數(shù)據(jù)卧须,Cell內實現(xiàn)的內容來自web瞬痘,使用異步加載板熊,緩存請求結果
九.渲染
1. 減少subviews的個數(shù)和層級
?子控件的層級越深,渲染到屏幕上所需要的計算量量就越大;如多用drawRect繪制元素干签,替代?view顯示
2. 少?用subviews的透明圖層
對于不透明的View拆撼,設置opaque為YES容劳,這樣在繪制該View時闸度,就不需要考慮被View覆蓋的其他內容(盡量設置Cell的view為opaque,避免GPU對Cell下?的內容 也進行繪制)
3. 避免CALayer特效(shadowPath) 給Cell中View加陰影會引起性能問題留量,如下面代碼會導致滾動時有明顯的卡頓:
view.layer.shadowColor = color.CGColor;
view.layer.shadowOffset = offset;
view.layer.shadowOpacity = 1;
view.layer.shadowRadius = radius;