性能優(yōu)化

性能優(yōu)化

參考文章:
http://www.itdecent.cn/p/c51106cbea05

一、tableView的優(yōu)化

1、使用tableViewCell復(fù)用,利用緩沖池。 每次刷新顯示都會(huì)去創(chuàng)建新的Cell,非常耗費(fèi)性能。
解決方案:首先創(chuàng)建一個(gè)靜態(tài)變量reuseID(代理方法返回Cell會(huì)調(diào)用很多次,防止重復(fù)創(chuàng)建,static保證只會(huì)被創(chuàng)建一次,提高性能),然后,從緩存池中取相應(yīng)identifier的Cell并更新數(shù)據(jù),如果沒有,才開始alloc新的Cell,并用identifier標(biāo)識(shí)Cell。每個(gè)Cell都會(huì)注冊(cè)一個(gè)identifier(重用標(biāo)識(shí)符)放入緩存池,當(dāng)需要調(diào)用的時(shí)候就直接從緩存池里找對(duì)應(yīng)的id,當(dāng)不需要時(shí)就放入緩存池等待調(diào)用。(移出屏幕的Cell才會(huì)放入緩存池中,并不會(huì)被release)所以在數(shù)據(jù)源方法中做出如下優(yōu)化:

2、heightForRow
如果是動(dòng)態(tài)計(jì)算的,將高度存入模型中。避免每次計(jì)算

3、異步繪制
如果需要對(duì)圖片進(jìn)行圓角處理等,可以通過CGContextRef方法性能更高

4、避免大量的圖片縮放、顏色漸變盡量顯示“大小剛好合適的圖片資源”

5、避免同步的從網(wǎng)絡(luò)、文件獲取數(shù)據(jù),Cell內(nèi)實(shí)現(xiàn)的內(nèi)容來(lái)自web,使用異步加載,緩存請(qǐng)求結(jié)果

6、渲染
a.減少subviews的個(gè)數(shù)和層級(jí)
子控件的層級(jí)越深,渲染到屏幕上所需要的計(jì)算量就越大;如多用drawRect繪制元素,替代用view顯示
b.少用subviews的透明圖層
對(duì)于不透明的View,設(shè)置opaque為YES,這樣在繪制該View時(shí),就不需要考慮被View覆蓋的其他內(nèi)容(盡量設(shè)置Cell的view為opaque,避免GPU對(duì)Cell下面的內(nèi)容也進(jìn)行繪制)
c.避免CALayer特效(shadowPath)
給Cell中View加陰影會(huì)引起性能問題,如下面代碼會(huì)導(dǎo)致滾動(dòng)時(shí)有明顯的卡頓:

二、程序啟動(dòng)優(yōu)化

1、開啟時(shí)間分析功能
在Xcode的菜單中選擇Project→Scheme→Edit Scheme...,然后找到Run → Environment Variables → +,添加name為DYLD_PRINT_STATISTICSvalue為1的環(huán)境變量。

2、結(jié)論分析
Total pre-main time: 94.33 milliseconds (100.0%)
dylib loading time: 61.87 milliseconds (65.5%)
rebase/binding time: 3.09 milliseconds (3.2%)
ObjC setup time: 10.78 milliseconds (11.4%)
initializer time: 18.50 milliseconds (19.6%)
slowest intializers :
libSystem.B.dylib : 3.59 milliseconds (3.8%)
libBacktraceRecording.dylib : 3.65 milliseconds (3.8%)
MyTest : 7.09 milliseconds (7.5%)

main()函數(shù)之前總共使用了94.33ms
在94.33ms中,加載動(dòng)態(tài)庫(kù)用了61.87ms,指針重定位使用了3.09ms,ObjC類初始化使用了10.78ms,各種初始化使用了18.50ms。
在初始化耗費(fèi)的18.50ms中,用時(shí)最多的三個(gè)初始化是libSystem.B.dylib、libBacktraceRecording.dylib以及MyTest。

動(dòng)態(tài)庫(kù)、ObjC 和ObjC的+load方法越多啟動(dòng)越慢

三、其他優(yōu)化建議

1.不要阻塞主線程

2.盡可能設(shè)置 View 為不透明

3.避免臃腫的 XIB 文件

4.啟用 GZIP 數(shù)據(jù)壓縮

5.View 的復(fù)用、懶加載

6、緩存
服務(wù)器的響應(yīng)信息(response)、圖片、計(jì)算值。比如:UITableView 的 row heights。

7.處理內(nèi)存警告
在 AppDelegate 中實(shí)現(xiàn) - [AppDelegate applicationDidReceiveMemoryWarning:] 代理方法。
在 UIViewController 中重載 didReceiveMemoryWarning 方法。
監(jiān)聽 UIApplicationDidReceiveMemoryWarningNotification 通知。

8.復(fù)用高開銷的對(duì)象

9.減少應(yīng)用啟動(dòng)時(shí)間
快速啟動(dòng)應(yīng)用對(duì)于用戶來(lái)說(shuō)可以留下很好的印象。尤其是第一次使用時(shí)。
保證應(yīng)用快速啟動(dòng)的指導(dǎo)原則:
盡量將啟動(dòng)過程中的處理分拆成各個(gè)異步處理流,比如:網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)訪問、數(shù)據(jù)解析等等。
避免臃腫的 XIB 文件,因?yàn)樗鼈儠?huì)在你的主線程中進(jìn)行加載。重申:Storyboard 沒這個(gè)問題,放心使用。
注意:在測(cè)試程序啟動(dòng)性能的時(shí)候,最好用與 Xcode 斷開連接的設(shè)備進(jìn)行測(cè)試。因?yàn)?watchdog 在使用 Xcode 進(jìn)行調(diào)試的時(shí)候是不會(huì)啟動(dòng)的。

10.使用 Autorelease Pool (內(nèi)存釋放池)

11.imageNamed 和 imageWithContentsOfFile
imageNamed:創(chuàng)建的對(duì)象會(huì)緩存到系統(tǒng)內(nèi)存中,不會(huì)立即釋放到內(nèi)存。好處是再次加載使用這種方式會(huì)減少讀取操作,加快程序運(yùn)行。缺點(diǎn):加載過多圖片會(huì)占用大量?jī)?nèi)存空間。
mageWithContentsOfFile創(chuàng)建的對(duì)象不會(huì)緩存到系統(tǒng)內(nèi)存中。好處是不產(chǎn)生緩存。缺點(diǎn):對(duì)于經(jīng)常使用的小圖片,會(huì)頻繁讀取。

 加載圖片:
  1->如果在項(xiàng)目中的Assets.xcassets(藍(lán)色文件夾)
    a.不可以NSBundle獲得資源路徑,然后imageWithContentsOfFile加載
    b.可以imageNamed加載

  2->如果在項(xiàng)目中真實(shí)文件夾(藍(lán)色文件夾,除Assets.xcassets):
    a.可以NSBundle獲得資源路徑,然后imageWithContentsOfFile加載。注意要帶文件夾路徑,例如
    [[NSBundle mainBundle]pathForResource:@"test.jpg" ofType:nil inDirectory:@"image"]
    b.不可以imageNamed加載

  3->如果在項(xiàng)目中虛擬文件夾(黃色文件夾)
    a.可以NSBundle獲得資源路徑,然后imageWithContentsOfFile加載
    b.可以imageNamed加載

12、延遲加載圖片
有時(shí)候在邊滾動(dòng)邊設(shè)置圖片的時(shí)候可能會(huì)有一定的影響,因此可以在滾動(dòng)的時(shí)候imageview不執(zhí)行setimage的操作,滾動(dòng)停止的時(shí)候才加載圖片,由于滾動(dòng)的時(shí)候NSRunloop是處于UITrackingRunLoopMode模式下,可以采用如下的方式,將設(shè)置圖片放到NSDefaultRunLoopMode模式下才進(jìn)行:
UIImage *downloadedImage = ...;
[self.avatarImageView performSelector:@selector(setImage:)
withObject:downloadedImage
afterDelay:0
inModes:@[NSDefaultRunLoopMode]];

13.減少離屏渲染(設(shè)置圓角和陰影的時(shí)候可以選用繪制的方法)

14.優(yōu)化 UITableView
通過正確的設(shè)置 reuseIdentifier 來(lái)重用 Cell。
盡量減少不必要的透明 View。
盡量避免漸變效果、圖片拉伸和離屏渲染。
當(dāng)不同的行的高度不一樣時(shí),盡量緩存它們的高度值。
如果 Cell 展示的內(nèi)容來(lái)自網(wǎng)絡(luò),確保用異步加載的方式來(lái)獲取數(shù)據(jù),并且緩存服務(wù)器的 response。
使用 shadowPath 來(lái)設(shè)置陰影效果。
盡量減少 subview 的數(shù)量,對(duì)于 subview 較多并且樣式多變的 Cell,可以考慮用異步繪制或重寫 drawRect。
盡量?jī)?yōu)化 - [UITableView tableView:cellForRowAtIndexPath:] 方法中的處理邏輯,如果確實(shí)要做一些處理,可以考慮做一次,緩存結(jié)果。
選擇合適的數(shù)據(jù)結(jié)構(gòu)來(lái)承載數(shù)據(jù),不同的數(shù)據(jù)結(jié)構(gòu)對(duì)不同操作的開銷是存在差異的。
對(duì)于 rowHeight、sectionFooterHeight、sectionHeaderHeight 盡量使用常量。

15.選擇合適的數(shù)據(jù)存儲(chǔ)方式
在 iOS 中可以用來(lái)進(jìn)行數(shù)據(jù)持有化的方案包括:
NSUserDefaults。只適合用來(lái)存小數(shù)據(jù)。
XML、JSON、Plist 等文件。JSON 和 XML 文件的差異在「選擇正確的數(shù)據(jù)格式」已經(jīng)說(shuō)過了。
使用 NSCoding 來(lái)存檔。NSCoding 同樣是對(duì)文件進(jìn)行讀寫,所以它也會(huì)面臨必須加載整個(gè)文件才能繼續(xù)的問題。
使用 SQLite 數(shù)據(jù)庫(kù)。可以配合 FMDB 使用。數(shù)據(jù)的相對(duì)文件來(lái)說(shuō)還是好處很多的,比如可以按需取數(shù)據(jù)、不用暴力查找等等。
使用 CoreData。也是數(shù)據(jù)庫(kù)技術(shù),跟 SQLite 的性能差異比較小。但是 CoreData 是一個(gè)對(duì)象圖譜模型,顯得更面向?qū)ο螅籗QLite 就是常規(guī)的 DBMS。

16.減少應(yīng)用啟動(dòng)時(shí)間
快速啟動(dòng)應(yīng)用對(duì)于用戶來(lái)說(shuō)可以留下很好的印象。尤其是第一次使用時(shí)。
保證應(yīng)用快速啟動(dòng)的指導(dǎo)原則:
盡量將啟動(dòng)過程中的處理分拆成各個(gè)異步處理流,比如:網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)訪問、數(shù)據(jù)解析等等。
避免臃腫的 XIB 文件,因?yàn)樗鼈儠?huì)在你的主線程中進(jìn)行加載。重申:Storyboard 沒這個(gè)問題,放心使用。
注意:在測(cè)試程序啟動(dòng)性能的時(shí)候,最好用與 Xcode 斷開連接的設(shè)備進(jìn)行測(cè)試。因?yàn)?watchdog 在使用 Xcode 進(jìn)行調(diào)試的時(shí)候是不會(huì)啟動(dòng)的。

17.使用 Autorelease Pool (內(nèi)存釋放池)

18.imageNamed 和 imageWithContentsOfFile

19.對(duì)于圓角可以使用一張中間圓形透明的圖覆蓋在上面,雖然這會(huì)引入blending操作,但是大部分情況下性能會(huì)比離屏渲染好。

20.利用枚舉遍歷數(shù)組,效率比f(wàn)or循環(huán)高

21.加載圖片時(shí)用imageWithContentsOfFiles 這樣不會(huì)講圖片緩存到內(nèi)存中,同時(shí)要避免圖片縮放,因?yàn)檫@是很消耗性能

22.處理內(nèi)存警告
UIViewController的默認(rèn)行為是移除一些不可見的view,這樣對(duì)內(nèi)存警報(bào)的處理是很必要的,若不重視,你的app就可能被系統(tǒng)殺掉。

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

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

  • 在開發(fā)iOS應(yīng)用程序時(shí),讓程序具有良好的性能是非常關(guān)鍵的。這也是用戶所期望的,如果你的程序運(yùn)行遲鈍或緩慢,會(huì)招致用...
    imkakaxi閱讀 1,127評(píng)論 0 0
  • 性能優(yōu)化 1.如何讓你的應(yīng)用程序更加省電? 答:(1)如果程序用到定位,需要在定位完畢之后關(guān)閉定位,或者降低定位的...
    丶逐漸閱讀 1,029評(píng)論 0 6
  • 一. 如何讓你的應(yīng)用程序更加省電?答:(1). 如果程序用到定位,需要在定位完畢之后關(guān)閉定位,或者降低定位的頻率,...
    Hevin_Chen閱讀 1,257評(píng)論 0 4
  • 一、如何提高一個(gè)應(yīng)用程序的性能?1、使用ARC減少內(nèi)存失誤,dealloc需要重寫并對(duì)屬性置nil。2、重用。3、...
    金歌漫舞閱讀 1,071評(píng)論 2 6
  • 寫在前面 本文來(lái)自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iO...
    seeek閱讀 596評(píng)論 0 0

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