導(dǎo)讀
性能對 iOS 應(yīng)用的開發(fā)尤其重要蒋譬,如果你的應(yīng)用失去反應(yīng)或者很慢,失望的用戶會把他們的失望寫滿App Store的評論。然而由于iOS設(shè)備的限制街立,有時搞好性能是一件難事。開發(fā)過程中你會有很多需要注意的事項(xiàng)埠通,你也很容易在做出選擇時忘記考慮性能影響赎离。
iOS最全性能優(yōu)化(上)http://www.reibang.com/p/bd91f0347000
iOS最全性能優(yōu)化(中)http://www.reibang.com/p/f86221a69d4c
iOS最全性能優(yōu)化(下)http://www.reibang.com/p/e47aba73d975
請耐心讀完這篇文章,為你未來的app提個速端辱!
目錄
我要給出的建議將分為三個不同的等級: 入門級梁剔、 中級和進(jìn)階級:
-
入門級(這是些你一定會經(jīng)常用在你app開發(fā)中的建議)
1. 用ARC管理內(nèi)存
2. 在正確的地方使用reuseIdentifier
3. 盡可能使Views透明
4. 避免龐大的XIB
5. 不要block主線程
6. 在Image Views中調(diào)整圖片大小
7. 選擇正確的Collection
8. 打開gzip壓縮
-
中級(這些是你可能在一些相對復(fù)雜情況下可能用到的)
9. 重用和延遲加載Views
10. Cache, Cache, 還是Cache!
11. 權(quán)衡渲染方法
12. 處理內(nèi)存警告
13. 重用大開銷的對象
14. 使用Sprite Sheets
15. 避免反復(fù)處理數(shù)據(jù)
16. 選擇正確的數(shù)據(jù)格式
17. 正確地設(shè)定Background Images
18. 減少使用Web特性
19. 設(shè)定Shadow Path
20. 優(yōu)化你的Table View
21. 選擇正確的數(shù)據(jù)存儲選項(xiàng)
-
進(jìn)階級(這些建議只應(yīng)該在你確信他們可以解決問題和得心應(yīng)手的情況下采用)
22. 加速啟動時間 23. 使用Autorelease Pool 24. 選擇是否緩存圖片 25. 盡量避免日期格式轉(zhuǎn)換
無需贅述舞蔽,讓我們進(jìn)入正題吧~
初學(xué)者性能提升
這個部分致力于一些能提高性能的基本改變荣病。但所有層次的開發(fā)者都有可能會從這個記錄了一些被忽視的項(xiàng)目的小小的性能備忘錄里獲得一些提升。
1.用ARC管理內(nèi)存
-
ARC(Automatic Reference Counting, 自動引用計數(shù))和iOS5一起發(fā)布渗柿,它避免了最常見的也就是經(jīng)常是由于我們忘記釋放內(nèi)存所造成的內(nèi)存泄露个盆。它自動為你管理retain和release的過程,所以你就不必去手動干預(yù)了朵栖。
下面是你會經(jīng)常用來去創(chuàng)建一個View的代碼段:
UIView *view = [[UIView alloc] init]; // ... [self.view addSubview:view]; [view release];
忘掉代碼段結(jié)尾的release簡直像記得吃飯一樣簡單颊亮。而ARC會自動在底層為你做這些工作。除了幫你避免內(nèi)存泄露陨溅,ARC還可以幫你提高性能终惑,它能保證釋放掉不再需要的對象的內(nèi)存。這都啥年代了门扇,你應(yīng)該在你的所有項(xiàng)目里使用ARC!
2.在正確的地方使用 reuseIdentifier
一個開發(fā)中常見的錯誤就是沒有給UITableViewCells雹有, UICollectionViewCells,甚至是UITableViewHeaderFooterViews設(shè)置正確的reuseIdentifier臼寄。
為了性能最優(yōu)化件舵,table view用
tableView:cellForRowAtIndexPath:
為rows分配cells的時候,它的數(shù)據(jù)應(yīng)該重用自UITableViewCell脯厨。 一個table view維持一個隊列的數(shù)據(jù)可重用的UITableViewCell對象铅祸。不使用reuseIdentifier的話,每顯示一行table view就不得不設(shè)置全新的cell。這對性能的影響可是相當(dāng)大的临梗,尤其會使app的滾動體驗(yàn)大打折扣涡扼。自iOS6起,除了UICollectionView的cells和補(bǔ)充views盟庞,你也應(yīng)該在header和footer views中使用reuseIdentifiers
3.盡量把views設(shè)置為完全不透明
如果你有透明的Views你應(yīng)該設(shè)置它們的opaque(不透明)屬性為YES吃沪。例如一個黑色半透明的可以設(shè)置為一個灰色不透明的View替代.原因是這會使系統(tǒng)用一個最優(yōu)的方式渲染這些views。這個簡單的屬性在IB或者代碼里都可以設(shè)定什猖。
-
Apple的文檔對于為圖片設(shè)置透明屬性的描述是:
(opaque)這個屬性給渲染系統(tǒng)提供了一個如何處理這個view的提示票彪。如果設(shè)為YES, 渲染系統(tǒng)就認(rèn)為這個view是完全不透明的不狮,這使得渲染系統(tǒng)優(yōu)化一些渲染過程和提高性能降铸。如果設(shè)置為NO,渲染系統(tǒng)正常地和其它內(nèi)容組成這個View摇零。默認(rèn)值是YES推掸。
在相對比較靜止的畫面中,設(shè)置這個屬性不會有太大影響驻仅。然而當(dāng)這個view嵌在scroll view里邊谅畅,或者是一個復(fù)雜動畫的一部分,不設(shè)置這個屬性的話會在很大程度上影響app的性能噪服。
-
換種說法毡泻,大家可能更好理解:
只要一個視圖的不透明度小于1,就會導(dǎo)致blending.blending操作在iOS的圖形處理器(GPU)中完成的,blending主要指的是混合像素顏色的計算。舉個例子,我們把兩個圖層疊加在一起,如果第一個圖層的有透明效果,則最終像素的顏色計算需要將第二個圖層也考慮進(jìn)來粘优。這一過程即為Blending牙捉。
為什么Blending會導(dǎo)致性能的損失?
原因是很直觀的,如果一個圖層是完全不透明的,則系統(tǒng)直接顯示該圖層的顏色即可敬飒。而如果圖層是帶透明效果的,則會引入更多的計算,因?yàn)樾枰严旅娴膱D層也包括進(jìn)來,進(jìn)行混合后顏色的計算邪铲。
4. 避免過于龐大的XIB
iOS5中加入的Storyboards(分鏡)正在快速取代XIB。然而XIB在一些場景中仍然很有用无拗。比如你的app需要適應(yīng)iOS5之前的設(shè)備带到,或者你有一個自定義的可重用的view,你就不可避免地要用到他們。
-
如果你不得不XIB的話英染,使他們盡量簡單揽惹。嘗試為每個Controller配置一個單獨(dú)的XIB,盡可能把一個View Controller的view層次結(jié)構(gòu)分散到單獨(dú)的XIB中去四康。
需要注意的是搪搏,當(dāng)你加載一個XIB的時候所有內(nèi)容都被放在了內(nèi)存里,包括任何圖片闪金。如果有一個不會即刻用到的view疯溺,你這就是在浪費(fèi)寶貴的內(nèi)存資源了论颅。Storyboards就是另一碼事兒了,storyboard僅在需要時實(shí)例化一個view controller.
當(dāng)你加載一個引用了圖片或者聲音資源的nib時囱嫩,nib加載代碼會把圖片和聲音文件寫進(jìn)內(nèi)存恃疯。在OS X中,圖片和聲音資源被緩存在named cache中以便將來用到時獲取墨闲。在iOS中今妄,僅圖片資源會被存進(jìn)named caches。取決于你所在的平臺鸳碧,使用NSImage 或UIImage 的
imageNamed:
方法來獲取圖片資源盾鳞。
5. 不要阻塞主線程
永遠(yuǎn)不要使主線程承擔(dān)過多。因?yàn)閁IKit在主線程上做所有工作瞻离,渲染腾仅,管理觸摸反應(yīng),回應(yīng)輸入等都需要在它上面完成琐脏。一直使用主線程的風(fēng)險就是如果你的代碼真的block了主線程,你的app會失去反應(yīng)
-
大部分阻礙主進(jìn)程的情形是你的app在做一些牽涉到讀寫外部資源的I/O操作缸兔,比如存儲或者網(wǎng)絡(luò)日裙。或者使用像 AFNetworking這樣的框架來異步地做這些操作惰蜜。
如果你需要做其它類型的需要耗費(fèi)巨大資源的操作(比如時間敏感的計算或者存儲讀寫)那就用 Grand Central Dispatch昂拂,或者 NSOperation 和 NSOperationQueues.
你可以使用
NSURLConnection
異步地做網(wǎng)絡(luò)操作:+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
6. 在Image Views中調(diào)整圖片大小
如果要在
UIImageView
中顯示一個來自bundle的圖片,你應(yīng)保證圖片的大小和UIImageView的大小相同抛猖。在運(yùn)行中縮放圖片是很耗費(fèi)資源的格侯,特別是UIImageView
嵌套在UIScrollView
中的情況下。如果圖片是從遠(yuǎn)端服務(wù)加載的你不能控制圖片大小财著,比如在下載前調(diào)整到合適大小的話联四,你可以在下載完成后,最好是用background thread撑教,縮放一次朝墩,然后在UIImageView中使用縮放后的圖片。
7. 選擇正確的Collection
學(xué)會選擇對業(yè)務(wù)場景最合適的類或者對象是寫出能效高的代碼的基礎(chǔ)伟姐。當(dāng)處理collections時這句話尤其正確收苏。
Apple有一個 Collections Programming Topics 的文檔詳盡介紹了可用的classes間的差別和你該在哪些場景中使用它們。這對于任何使用collections的人來說是一個必讀的文檔愤兵。
呵呵鹿霸,我就知道你因?yàn)樘L沒看…這是一些常見collection的總結(jié):
Arrays: 有序的一組值。使用index來lookup很快秆乳,使用value lookup很慢懦鼠, 插入/刪除很慢。
Dictionaries: 存儲鍵值對。 用鍵來查找比較快葛闷。
Sets: 無序的一組值憋槐。用值來查找很快,插入/刪除很快淑趾。
8. 打開gzip壓縮
大量app依賴于遠(yuǎn)端資源和第三方API阳仔,你可能會開發(fā)一個需要從遠(yuǎn)端下載XML, JSON, HTML或者其它格式的app。
問題是我們的目標(biāo)是移動設(shè)備扣泊,因此你就不能指望網(wǎng)絡(luò)狀況有多好近范。一個用戶現(xiàn)在還在edge網(wǎng)絡(luò),下一分鐘可能就切換到了3G延蟹。不論什么場景评矩,你肯定不想讓你的用戶等太長時間。
減小文檔的一個方式就是在服務(wù)端和你的app中打開gzip阱飘。這對于文字這種能有更高壓縮率的數(shù)據(jù)來說會有更顯著的效用斥杜。好消息是,iOS已經(jīng)在NSURLConnection中默認(rèn)支持了gzip壓縮沥匈,當(dāng)然AFNetworking這些基于它的框架亦然蔗喂。像Google App Engine這些云服務(wù)提供者也已經(jīng)支持了壓縮輸出。