iOS程序性能優(yōu)化的技巧
1. 用ARC管理內(nèi)存
ARC(Automatic ReferenceCounting, 自動引用計數(shù))和iOS5一起發(fā)布,它避免了最常見的也就是經(jīng)常是由于我們忘記釋放內(nèi)存所造成的內(nèi)存泄露。它自動為你管理retain和release的過程,所以你就不必去手動干預了。忘掉代碼段結(jié)尾的release簡直像記得吃飯一樣簡單。而ARC會自動在底層為你做這些工作。除了幫你避免內(nèi)存泄露,ARC還可以幫你提高性能,它能保證釋放掉不再需要的對象的內(nèi)存。
2.盡量把views設置為透明
如果你有透明的Views你應該設置它們的opaque屬性為YES。
原因是這會使系統(tǒng)用一個最優(yōu)的方式渲染這些views。這個簡單的屬性在IB或者代碼里都可以設定。
Apple的文檔對于為圖片設置透明屬性的描述是:
(opaque)這個屬性給渲染系統(tǒng)提供了一個如何處理這個view的提示。如果設為YES,渲染系統(tǒng)就認為這個view是完全不透明的,這使得渲染系統(tǒng)優(yōu)化一些渲染過程和提高性能。如果設置為NO,渲染系統(tǒng)正常地和其它內(nèi)容組成這個View。默認值是YES。
在相對比較靜止的畫面中,設置這個屬性不會有太大影響。然而當這個view嵌在scroll view里邊,或者是一個復雜動畫的一部分,不設置這個屬性的話會在很大程度上影響app的性能。
你可以在模擬器中用DebugColor Blended Layers選項來發(fā)現(xiàn)哪些view沒有被設置為opaque。目標就是,能設為opaque的就全設為opaque!
這里有一點需要注意,只要是有中文字符的Label,哪怕你設置成不透明,模擬器中這個Label依然會變紅,這個猜測是字符繪制的時候出的問題,這個目前沒找到好的解決方法。
3.避免過于龐大的XIB
iOS5中加入的Storyboards(分鏡)正在快速取代XIB。然而XIB在一些場景中仍然很有用。比如你的app需要適應iOS5之前的設備,或者你有一個自定義的可重用的view,你就不可避免地要用到他們。
如果你不得不XIB的話,使他們盡量簡單。嘗試為每個Controller配置一個單獨的XIB,盡可能把一個View Controller的view層次結(jié)構(gòu)分散到單獨的XIB中去。
需要注意的是,當你加載一個XIB的時候所有內(nèi)容都被放在了內(nèi)存里,包括任何圖片。如果有一個不會即刻用到的view,你這就是在浪費寶貴的內(nèi)存資源了。Storyboards就是另一碼事兒了,storyboard僅在需要時實例化一個view controller.
當家在XIB是,所有圖片都被chache,如果你在做OS X開發(fā)的話,聲音文件也是。Apple在相關(guān)文檔中的記述是:
當你加載一個引用了圖片或者聲音資源的nib時,nib加載代碼會把圖片和聲音文件寫進內(nèi)存。在OS X中,圖片和聲音資源被緩存在named cache中以便將來用到時獲取。在iOS中,僅圖片資源會被存進named caches。取決于你所在的平臺,使用NSImage 或UIImage的imageNamed:方法來獲取圖片資源。
這個問題我深有體會,用xib寫的界面加載速度比直接用代碼寫的要慢好多
4. 在Image Views中調(diào)整圖片大小
如果要在UIImageView中顯示一個來自bundle的圖片,你應保證圖片的大小和UIImageView的大小相同。在運行中縮放圖片是很耗費資源的,特別是UIImageView嵌套在UIScrollView中的情況下。
如果圖片是從遠端服務加載的你不能控制圖片大小,比如在下載前調(diào)整到合適大小的話,你可以在下載完成后,最好是用background thread,縮放一次,然后在UIImageView中使用縮放后的圖片。
5. 選擇正確的Collection
學會選擇對業(yè)務場景最合適的類或者對象是寫出能效高的代碼的基礎。當處理collections時這句話尤其正確。
一些常見collection的總結(jié):
Arrays: 有序的一組值。使用index來lookup很快,使用value lookup很慢,插入/刪除很慢。
Dictionaries: 存儲鍵值對。用鍵來查找比較快。
Sets: 無序的一組值。用值來查找很快,插入/刪除很快。因為Set用到了哈希,所以插入刪除查找速度比Array快很多
6. 打開gzip壓縮
大量app依賴于遠端資源和第三方API,你可能會開發(fā)一個需要從遠端下載XML, JSON, HTML或者其它格式的app。
問題是我們的目標是移動設備,因此你就不能指望網(wǎng)絡狀況有多好。一個用戶現(xiàn)在還在edge網(wǎng)絡,下一分鐘可能就切換到了3G。不論什么場景,你肯定不想讓你的用戶等太長時間。
減小文檔的一個方式就是在服務端和你的app中打開gzip。這對于文字這種能有更高壓縮率的數(shù)據(jù)來說會有更顯著的效用。
好消息是,iOS已經(jīng)在NSURLConnection中默認支持了gzip壓縮,當然AFNetworking這些基于它的框架亦然。像Google App Engine這些云服務提供者也已經(jīng)支持了壓縮輸出。
7. 重用和延遲加載(lazy load) Views
更多的view意味著更多的渲染,也就是更多的CPU和內(nèi)存消耗,對于那種嵌套了很多view在UIScrollView里邊的app更是如此。
這里我們用到的技巧就是模仿UITableView和UICollectionView的操作:不要一次創(chuàng)建所有的subview,而是當需要時才創(chuàng)建,當它們完成了使命,把他們放進一個可重用的隊列中。
這樣的話你就只需要在滾動發(fā)生時創(chuàng)建你的views,避免了不劃算的內(nèi)存分配。
創(chuàng)建views的能效問題也適用于你app的其它方面。想象一下一個用戶點擊一個按鈕的時候需要呈現(xiàn)一個view的場景。有兩種實現(xiàn)方法:
創(chuàng)建并隱藏這個view當這個screen加載的時候,當需要時顯示它; 當需要時才創(chuàng)建并展示。每個方案都有其優(yōu)缺點。用第一種方案的話因為你需要一開始就創(chuàng)建一個view并保持它直到不再使用,這就會更加消耗內(nèi)存。然而這也會使你的app操作更敏感因為當用戶點擊按鈕的時候它只需要改變一下這個view的可見性。
第二種方案則相反-消耗更少內(nèi)存,但是會在點擊按鈕的時候比第一種稍顯卡頓。
8.權(quán)衡渲染方法
在iOS中可以有很多方法做出漂亮的按鈕。你可以用整幅的圖片,可調(diào)大小的圖片,或者可以用CALayer, CoreGraphics甚至OpenGL來畫它們。當然每個不同的解決方法都有不同的復雜程度和相應的性能。
簡單來說,就是用事先渲染好的圖片更快一些,因為如此一來iOS就免去了創(chuàng)建一個圖片再畫東西上去然后顯示在屏幕上的程序。問題是你需要把所有你需要用到的圖片放到app的bundle里面,這樣就增加了體積?這就是使用可變大小的圖片更好的地方了:你可以省去一些不必要的空間,也不需要再為不同的元素(比如按鈕)來做不同的圖。
然而,使用圖片也意味著你失去了使用代碼調(diào)整圖片的機動性,你需要一遍又一遍不斷地重做他們,這樣就很浪費時間了,而且你如果要做一個動畫效果,雖然每幅圖只是一些細節(jié)的變化你就需要很多的圖片造成bundle大小的不斷增大。
總得來說,你需要權(quán)衡一下利弊,到底是要性能能還是要bundle保持合適的大小。
9.處理內(nèi)存警告
一旦系統(tǒng)內(nèi)存過低,iOS會通知所有運行中app。在官方文檔中是這樣記述:
如果你的app收到了內(nèi)存警告,它就需要盡可能釋放更多的內(nèi)存。最佳方式是移除對緩存,圖片object和其他一些可以重創(chuàng)建的objects的strong references.
幸運的是,UIKit提供了幾種收集低內(nèi)存警告的方法:
在app delegate中使用applicationDidReceiveMemoryWarning:的方法
在你的自定義UIViewController的子類(subclass)中覆蓋didReceiveMemoryWarning
注冊并接收 UIApplicationDidReceiveMemoryWarningNotification的通知
一旦收到這類通知,你就需要釋放任何不必要的內(nèi)存使用。
例如,UIViewController的默認行為是移除一些不可見的view,它的一些子類則可以補充這個方法,刪掉一些額外的數(shù)據(jù)結(jié)構(gòu)。一個有圖片緩存的app可以移除不在屏幕上顯示的圖片。
這樣對內(nèi)存警報的處理是很必要的,若不重視,你的app就可能被系統(tǒng)殺掉。
然而,當你一定要確認你所選擇的object是可以被重現(xiàn)創(chuàng)建的來釋放內(nèi)存。一定要在開發(fā)中用模擬器中的內(nèi)存提醒模擬去測試一下。
當然,現(xiàn)在iOS設備運行內(nèi)存越來越大,這一點很難出現(xiàn)了
10. 使用Sprite Sheets
Sprite sheet可以讓渲染速度加快,甚至比標準的屏幕渲染方法節(jié)省內(nèi)存。
11.避免反復處理數(shù)據(jù)
許多應用需要從服務器加載功能所需的常為JSON或者XML格式的數(shù)據(jù)。在服務器端和客戶端使用相同的數(shù)據(jù)結(jié)構(gòu)很重要。在內(nèi)存中操作數(shù)據(jù)使它們滿足你的數(shù)據(jù)結(jié)構(gòu)是開銷很大的。
比如你需要數(shù)據(jù)來展示一個table view,最好直接從服務器取array結(jié)構(gòu)的數(shù)據(jù)以避免額外的中間數(shù)據(jù)結(jié)構(gòu)改變。
類似的,如果需要從特定key中取數(shù)據(jù),那么就使用鍵值對的dictionary。
這一點在處理大量數(shù)據(jù)的時候極為重要,用空間換時間的方法也許是極好的。
12.選擇正確的數(shù)據(jù)格式
從app和網(wǎng)絡服務間傳輸數(shù)據(jù)有很多方案,最常見的就是JSON和XML。你需要選擇對你的app來說最合適的一個。
解析JSON會比XML更快一些,JSON也通常更小更便于傳輸。從iOS5起有了官方內(nèi)建的JSON deserialization就更加方便使用了。
但是XML也有XML的好處,比如使用SAX來解析XML就像解析本地文件一樣,你不需像解析json一樣等到整個文檔下載完成才開始解析。當你處理很大的數(shù)據(jù)的時候就會極大地減低內(nèi)存消耗和增加性能。
以上就是iOS程序性能優(yōu)化的建議的詳細內(nèi)容,更多關(guān)于ios 程序性能優(yōu)化的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
