[转]25个增强iOS应用程序性能的提示和技巧
在開發iOS應用程序時,讓程序具有良好的性能是非常關鍵的。這也是用戶所期望的,如果你的程序運行遲鈍或緩慢,會招致用戶的差評。然而由于iOS設備的局限性,有時候要想獲得良好的性能,是很困難的。在開發過程中,有許多事項需要記住,并且關于性能影響很容易就忘記。
?
本文收集了25個關于可以提升程序性能的提示和技巧,把性能優化技巧分為3個不同的等級:初級、中級和高級
?
初級
在開發過程中,下面這些初級技巧需要時刻注意:
?
1.使用ARC進行內存管理
2.在適當的情況下使用reuseIdentifier
3.盡可能將View設置為不透明(Opaque)
4.避免臃腫的XIBs
5.不要阻塞主線程
6.讓圖片的大小跟UIImageView一樣
7.選擇正確的集合
8.使用GZIP壓縮
?
1) 使用ARC進行內存管理
ARC是在iOS 5中發布的,它解決了最常見的內存泄露問題——也是開發者最容易健忘的。ARC的全稱是“Automatic Reference Counting”——自動引用計數,它會自動的在代碼中做retain/release工作,開發者不用再手動處理。
?
下面是創建一個View通用的一些代碼塊:
在上面代碼結束的地方很容易會忘記調用release。不過當使用ARC時,ARC會在后臺自動的幫你調用release。
?
ARC除了能避免內存泄露外,還有助于程序性能的提升:當程序中的對象不再需要的時候,ARC會自動銷毀對象。所以,你應該在工程中使用ARC。
?
下面是學習ARC的一些資源:
蘋果的官方文檔
Matthijs Hollemans的初級ARC
Tony Dahbura的如何在Cocos2D 2.X工程中使用ARC
如果你仍然不確定ARC帶來的好處,那么看一些這篇文章:8個關于ARC的神話——這能夠讓你相信你應該在工程中使用ARC!
值得注意的是,ARC并不能避免所有的內存泄露。使用ARC之后,工程中可能還會有內存泄露,不過引起這些內存泄露的主要原因是:block,retain循環,對CoreFoundation對象(通常是C結構)管理不善,以及真的是代碼沒寫好。
這里有一篇文章是介紹哪些問題是ARC不能解決的?— 以及如何處理這些問題。
?
2) 在適當的情況下使用reuseIdentifier
在適當的情況使用reuseIdentifier
在iOS程序開發中一個普遍性的錯誤就是沒有正確的為UITableViewCells、UICollectionViewCells和UITableViewHeaderFooterViews設置reuseIdentifier。
為了獲得最佳性能,當在tableView:cellForRowAtIndexPath:方法中返回cell時,table view的數據源一般會重用UITableViewCell對象。table view維護著UITableViewCell對象的一個隊列或者列表,這些數據源已經被標記為重用了。
?
如果沒有使用reuseIdentifier會發生什么?如果你在程序中沒有使用reuseIdentifier,table view每次顯示一個row時,都會配置一個全新的cell。這其實是一個非常消耗資源的操作,并且會影響程序中table view滾動的效率。
?
自iOS 6以來,你可能還希望header和footer views,以及UICollectionView的cell和supplementary views。
?
為了使用reuseIdentifiers,在table view請求一個新的cell時,在數據源中調用下面的方法:
如果table view維護的UITableViewCell隊列或列表中有可用的cell,則從隊列從移除一個已經存在的cell,如果沒有的話,就從之前注冊的nib文件或類中創建一個新的cell。如果沒有可以重用的cell,并且沒有注冊nib文件或類,tableview的dequeueReusableCellWithIdentifier:方法會返回一個nil。
3) 盡可能將View設置為不透明(Opaque)
盡量將view設置為Opaque
?
如果view是不透明的,那么應該將其opaque屬性設置為YES。為什么要這樣做呢?這樣設置可以讓系統以最優的方式來繪制view。opaque屬性可以在Interface Builder或代碼中設置。
?
蘋果的官方文檔對opaque屬性有如下解釋:
This property provides a hint to the drawing system as to how it should treat the view. If set to YES, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance. If set to NO, the drawing system composites the view normally with other content. The default value of this property is YES.
(opaque屬性提示繪制系統如何處理view。如果opaque設置為YES,繪圖系統會將view看為完全不透明,這樣繪圖系統就可以優化一些繪制操作以提升性能。如果設置為NO,那么繪圖系統結合其它內容來處理view。默認情況下,這個屬性是YES。)
?
如果屏幕是靜止的,那么這個opaque屬性的設置與否不是一個大問題。但是,如果view是嵌入到scroll view中的,或者是復雜動畫的一部分,不將設置這個屬性的話肯定會影響程序的性能!可以通過模擬器的Debug\Color Blended Layers選項來查看哪些view沒有設置為不透明。為了程序的性能,盡可能的將view設置為不透明!
?
4) 避免臃腫的XIBs
避免臃腫的XIBs
?
在iOS 5中開始使用Storyboards,并且將替代XIBs。不過在有些情況下XIBs仍然有用。如果你的程序需要運行在裝有iOS 5之前版本的設備上,或者要自定義可重用的view,那么是避免不了要使用XIBs的。
?
如果必須要使用XIBs的話,盡量讓XIBs文件簡單。并且每個view controller對于一個XIB文件,如果可以的話,把一個view controller的view不同的層次單獨分到一個XIBs文件中。
?
(注意:當把一個XIB文件加載到內存時,XIB文件中的所有內容都將被加載到內存中,包括圖片。如果有一個view還不立即使用的話,就會造成內存的浪費。而這在storyboard中是不會發生的,因為storyboard還在需要的時候才實例化一個view controller。)
?
當加載XIB時,所有涉及到的圖片都將被緩存,并且如果是開發的程序是針對OS X的話,聲音文件也會被加載。蘋果的官方文檔這樣說:
When you load a nib file that contains references to image or sound resources, the nib-loading code reads the actual image or sound file into memory and and caches it. In OS X, image and sound resources are stored in named caches so that you can access them later if needed. In iOS, only image resources are stored in named caches. To access images, you use the imageNamed: method of NSImage or UIImage, depending on your platform.
(當加載一個nib文件時,也會將nib文件涉及到的圖片或聲音資源加載到內存中,nib-loading代碼會將實際的圖片或聲音文件讀取到內存中,并一直緩存著。在OS X中,圖片和聲音資源都存儲在命名緩存中,這樣之后如果需要的話,可以對其進行訪問。在iOS中,只有圖片資源被存儲到命名緩存中。要訪問圖片的話,使用NSImage或UIImage(根據不同的系統)的imageNamed:方法即可。)
?
顯然,在使用storyboard時也會發生類似的緩存操作;不過我沒有找到相關內容的任何資料。想要學習storyboard的更多知識嗎?可以看看Matthijs Hollemans寫的iOS 5中:初級Storyboard Part 1和Part2。
?
5) 不要阻塞主線程
永遠都不要在主線程做繁重的任務。因為UIKit的左右任務都在主線程中進行,例如繪制、觸摸管理和輸入響應。
在主線程做所有任務的風險是:如果你的代碼阻塞了主線程,那么程序將出現反應遲鈍。這回招致用戶在App Store上對程序的差評!
?
在執行I/O操作中,大多數情況下都會祖塞主線程,這些操作需要從讀寫外部資源,例如磁盤或者網絡。
?
關于網絡操作可以使用NSURLConnection的如下方法,以異步的方式來執行:
或者使用第三方框架,例如AFNetworking。
?
如果你需要做一些其它類型開銷很大的操作(例如執行一個時間密集型的計算或者對磁盤進行讀寫),那么就使用GCD(Grand Central Dispatch),或NSOperations 和 NSOperationQueues。
?
下面的代碼是使用GCD的一個模板:
如上代碼,為什么在第一個dispatch_async里面還嵌套了一個dispatch_async呢?這是因為關于UIKit相關的代碼需要在主線程里面執行。
可以看看Ray Wenderlich中的教程:iOS中多線程和GCD—初級,以及Soheil Azarpour的如何使用NSOperations和NSOperationQueues教程。
?
6) 讓圖片的大小跟UIImageView一樣
確保圖片和UIImageView大小一致
如果需要將程序bundle中的圖片顯示到UIImageView中,請確保圖片和UIImageView的大小是一樣的。因為圖片的縮放非常耗費資源,特別是將UIImageView嵌入到UIScrollView中。
如果是從遠程服務中下載圖片,有時候你控制不了圖片的尺寸,或者在下載之前無法在服務器上進行圖片的縮放。這種情況,當圖片下載完之后,你可以手動進行圖片的縮放——做好是在后臺線程中!——然后再在UIImageView中使用縮放過的圖片。
?
?
7) 選擇正確的集合
選擇正確的集合
學習使用最適合的類或對象是編寫高效代碼的基礎。特別是在處理集合數據時,尤為重要。
蘋果的官網上有一篇文章:集合編程主題(Collections Programming Topics)——詳細的介紹了在集合數據中可以使用的類,以及什么情況下使用哪個類。在使用集合時,每個開發者都應該閱讀一下這個文檔。
太長,不想閱讀(TLDR)?下面是常見集合類型的一個簡介:
?數組:是一個值按順序排列的一個列表。根據索引可以快速查找,不過根據值進行查找就比較慢,另外插入和刪除也比較慢。
?字典:? 存儲鍵/值對。根據鍵可以快速查找。
?Sets:? 是一個值無序排列的列表,根據值可以快速查找,另外插入和刪除也比較快。
8) 使用GZIP壓縮
使用GZIP壓縮
越來越多的程序依賴于外部數據,這些數據一般來自遠程服務器或者其它的外部APIs。有時候你需要開發一個程序來下載一些數據,這些數據可以是XML,JSON,HTML或者其它一些文本格式。
?
問題是在移動設備上的網絡是不確定的。用戶的設備可能在EDGE網絡一分鐘,然后接著又在3G網絡中。不管在什么情況下,都不要讓用戶等待。
?
有一個可以優化的選擇:使用GZIP對網絡傳輸中的數據進行壓縮,這樣可以減小文件的大小,并加快下載的速度。壓縮對于文本數據特別有用,因為文本具有很高的壓縮比。
?
iOS中,如果使用NSURLConnection,那么默認情況下已經支持GZIP壓縮了,并且基于NSURLConnection的框架頁支持GZIP壓縮,如AFNetworking。甚至有些云服務提供商已經提供發送經壓縮過的響應內容,例如Google App Engine。
?
這里有一篇關于GZIP壓縮很好的文章,介紹了如何在Apache活IIS服務器中開啟支持GZIP壓縮。
?
在性能優化時,當你碰到一些復雜的問題,應該注意和使用如下技巧:
9.重用和延遲加載View
10.緩存、緩存、緩存
11.考慮繪制
12.處理內存警告
13.重用花銷很大的對象
14.使用Sprite Sheets
15.避免重新處理數據
16.選擇正確的數據格式
17.設置適當的背景圖片
18.降低Web內容的影響
19.設置陰影路徑
20.優化TableView
21.選擇正確的數據存儲方式
?
中級性能提升
現在,在進行代碼優化時,你已經能夠完成一些初級性能優化了。但是下面還有另外一些優化方案,雖然可能不太明顯(取決于程序的架構和相關代碼),但是,如果能夠正確的利用好這些方案,那么它們對性能的優化將非常明顯!
9) 重用和延遲加載View
程序界面中包含更多的view,意味著界面在顯示的時候,需要進行更多的繪制任務;也就意味著需要消耗更多的CPU和內存資源。特別是在一個UIScrollView里面加入了許多view。
?
這種情況的管理技巧可以參考UITableView和UICollectionView的行為:不要一次性創建所有的subview,而是在需要的時候在創建view,并且當view使用完畢時候將它們添加到重用隊列中。
?
這樣就可以僅在UIScrollView滾動的時候才配置view,以此可以避免分配創建view的帶來的成本——這可能是非常耗資源的。
?
現在有這樣的一個問題:在程序中需要顯示的view在什么時機創建(比如說,當用戶點擊某個按鈕,需要顯示某個view)。這里有兩種可選方法:
在屏幕第一次加載以及隱藏的時候,創建view;然后在需要的時候,再把view顯示出來。
直到需要顯示view的時候,才創建并顯示view。
每種方法都有各自的優點和缺點。第一種方法需要消耗更多的內容,因為創建出來的view一直占據著內存,直到view被release掉。不過,使用這種方法,當用戶點擊按鈕時,程序會很快的顯示出view,因為只需要修改一下view的可見性即可。而第二種方法則產生相反的效果;當需要的時候猜創建view,這會消耗更少的內存;不過,當用戶點擊按鈕的時候,不會立即顯示出view。
10) 緩存、緩存、緩存
在開發程序時,一個重要的規則就是“緩存重要的內容”——這些內容一般不會改變,并且訪問的頻率比較高。
?
可以緩存寫什么內容呢?比如遠程服務器的響應內容,圖片,甚至是計算結果,比如UITableView的行高。
?
NSURLConnection根據HTTP頭的處理過程,已經把一些資源緩存到磁盤和內存中了。你甚至可以手動創建一個NSURLRequest ,讓其只加載緩存的值。
下面的代碼片段一般用在為圖片創建一個NSURLRequest:
注意:你可以使用NSURLConnection抓取一個URL請求,但是同樣可以使用AFNetworking來抓取,這種方法不用修改所有網絡相關的代碼——這是一個技巧!
?
更多關于HTTP 緩存, NSURLCache, NSURLConnection 以及相關的內容, 那么看一下NSHipster中的the NSURLCache entry。
?
如果你需要緩存的內容沒涉及到HTTP請求,那使用NSCache。NSCache的外觀和行為與NSDictionary類似, 但是,當系統需要回收內存時,NSCache會自動的里面存儲的內容。Mattt Thompson 在NSHipster上寫了一篇關于NSCache非常不錯的文章。
?
更多關于HTTP緩存的內容,建議讀一下Google的這篇文章:best-practices document on HTTP caching。
11) 考慮繪制
在iOS中制作漂亮的按鈕有多種方法。可以使用全尺寸圖片,可縮放圖片,或使用CALayer, CoreGraphics, 甚至是OpenGL來手動測量和繪制按鈕。
?
這些方法的復雜程度不同,性能也有區別。這篇關于iOS中圖形性能的文章值得一讀。其中Andy Matuschak(曾經是蘋果的UIKit小組的組員)對這篇文章的評論中,對于不同的方法及其性能權衡有非常好的一個見解。
?
簡單來說,使用預渲染圖片技術是最快的,因為iOS中不用等到在屏幕上顯示的時候才創建圖形和對形狀進行繪制(圖片已經創建好了!)。這樣帶來的問題是需要把所有的圖片都放到程序bundle中,從而增加了程序的大小。因此使用可伸縮圖片在這里將排上用場了:可以移除“浪費”空間的圖片——iOS可以重復利用。并且針對不同的元素(例如按鈕)不需要創建不同的圖片。
?
不過,使用圖片的話會失去代碼對圖片的控制能力,進而針對不同的程序,就需要重復的生成每一個需要的圖片,并反復的放到每個程序中。這個處理過程一般會比較慢。另外一點就是如果你需要一個動畫,或者許多圖片都要進行輕微的調整(比如多個顏色的覆蓋),那么需要在程序中加入許多圖片,進而增加了程序bundle的大小。
?
總的來說,要考慮一下什么才是最重要的:繪制性能還是程序大小。一般來說都重要,所以在同一個工程中,應該兩種都應考慮。
12) 處理內存警告
當系統內存偏低時,iOS會通知所有在運行的程序。蘋果的官方文檔中介紹了如何處理低內存警告:
If your app receives this warning, it must free up as much memory as possible. The best way to do this is to remove strong references to caches, image objects, and other data objects that can be recreated later.
?
如果程序收到了低內存警告,在程序中必須盡量釋放內存。最佳方法就是移除強引用的涉及到的緩存,圖片對象,以及其它可以在之后使用時還可以重新創建的數據對象。
?
UIKit中提供了如下幾種方法來接收低內存(low-memory)警告:
實現app delegate中的applicationDidReceiveMemoryWarning: 方法。
在UIViewController子類中重寫(Override)didReceiveMemoryWarning方法。
在通知中心里面注冊UIApplicationDidReceiveMemoryWarningNotificatio通知。
在收到以上任意的警告時,需要立即釋放任何不需要的內存。
?
例如,UIViewController的默認情況是清除掉當前不可見的view;在UIViewController的子類中,可以清除一些額外的數據。程序中不沒有顯示在當前屏幕中的圖片也可以release掉。
?
當收到低內存警告時,盡量釋放內存是非常重要的。否則,運行中的程序有可能會被系統殺掉。
?
不過,在清除內存時要注意一下:確保被清除的對象之后還可以被創建出來。另外,在開發程序的時候,請使用iOS模擬器中的模擬內存警告功能對程序進行測試!
13) 重用花銷很大的對象
有些對象的初始化非常慢——比如NSDateFormatter和NSCalendar。不過有時候可以避免使用這些對象,例如在解析JSON/XML中的日期時。
當使用這些對象時,為了避免性能上的瓶頸,可以嘗試盡量重用這些對象——在類中添加一個屬性或者創建一個靜態變量。
?
注意,如果使用靜態變量的話,對象會在程序運行的時候一直存在,就像單例一樣。
?
下面的代碼演示創建一個延遲加載的日期格式屬性。第一次調用屬性的時候,會創建一個新的日期格式。之后再調用的話,會返回已經創建好的實例對象:
另外,還需要記住的是在設置NSDateFormatter的日期格式時,同樣跟創建新的一個NSDateFormatter實例對象時一樣慢!因此,在程序中如果需要頻繁的處理日期格式,那么對NSDateFormatter進行重用是非常好的。
?
14) 使用Sprite Sheets
使用sprite sheets
你是一個游戲開發者嗎?是的話那么sprite sheets是最佳選擇之一。使用Sprite sheets跟常用的繪制方法比起來,繪制更快,并且消耗更少的內存。
下面是兩個非常不錯的sprite sheets教程:
如何在Cocos2D中使用動畫和Sprite Sheets?
如何在Cocos2D中使用紋理包(Texture Packer)和像素格式來創建并優化Sprite Sheets??。(第二個教程詳細的介紹了像素格式——在游戲中可以衡量性能的影響)
?
如果還不熟悉sprite sheets,可以看看這里的介紹:SpriteSheets – 視頻, Part 1和?Part 2?。這兩個視頻的作者是Andreas L?w, 他是紋理包(Texture Packer)的創建者, 紋理包是創建sprite sheets的重要工具。
?
除了使用sprite sheets外,這里還介紹了一些用于游戲開發中的技巧,例如,如果你有很多sprite(比如射擊類游戲中),那么可以重用sprite,而不用每次都創建sprite。
15) 避免重新處理數據
許多程序都需要從遠程服務器中獲取數據,以滿足程序的需求。這些數據一般是JSON或XML格式。在請求和接收數據時,使用相同的數據結構非常重要。
?
為什么呢?在內存中把數據轉換為適合程序的數據格式是需要付出額外代價的。
?
例如,如果你需要在table view中顯示一些數據,那么請求和接收的數據格式最好是數組格式的,這樣可以避免一些中間操作——將數據轉換為適合程序使用的數據結構。
?
類似的,如果程序是根據鍵來訪問具體的值,那么最好請求和接收一個鍵/值對字典。
?
在第一時間獲得的數據就是所需要格式的,可以避免將數據轉換為適合程序的數據格式帶來的額外代價。
16) 選擇正確的數據格式
選擇正確的數據格式
?
將數據從程序傳到網絡服務器中有多種方法,其中使用的數據格式基本都是JSON和XML。你需要做的就是在程序中選擇正確的數據格式。
?
JSON的解析速度非常快,并且要比XML小得多,也就意味著只需要傳輸更少數據。并且在iOS5之后,已經有內置的JSON反序列化API了,所以使用JSON是很容易的。
?
不過XML也有它自己的優勢:如果使用SAX方法來解析XML,那么可以邊讀XML邊解析,并不用等到全部的XML獲取到了才開始解析,這與JSON是不同的。當處理大量數據時,這種方法可以提升性能并減少內存的消耗。
17) 設置適當的背景圖片
在iOS編碼中,跟別的許多東西類似,這里也有兩種方法來給view設置一個背景圖片:
?
1.可以使用UIColor的colorWithPatternImge方法來創建一個顏色,并將這個顏色設置為view的背景顏色。
2.可以給view添加一個UIImageView子視圖。
?
如果你有一個全尺寸的背景圖片,那么應該使用UIImageView,因為UIColor的colorWithPatternImge方法是用來創建小圖片的——該圖片會被重復使用。此時使用UIImageView會節省很多內存。
不過,如果你計劃用小圖片當做背景,那么應該使用UIColor的colorWithPatternImge方法。這種情況下繪制速度會很快,并且不會消耗大量的內存。
18) 降低Web內容的影響
UIWebView非常有用。用它可以很容易的顯示web內容,甚至可以構建UIKit空間難以顯示的內容。
?
不過,你可以能已經注意到程序中使用的UIWebView組建沒有蘋果的Safari程序快。這是因為JIT編譯限制了WebKit的Nitro引擎的使用。
?
因此為了獲得更加的性能,需要調整一下HTML的大小。首先就是盡量的擺脫JavaScript,并避免使用大的礦建,例如jQuery。有時候使用原始的JavaScript要比別的框架快。
?
另外,盡量的異步加載JavaScript文件——特別是不直接影響到頁面行為時,例如分析腳本。
?
最后——讓使用到的圖片,跟實際需要的一樣大小。如之前提到的,盡量使用sprite sheets,以此節省內存和提升速度。
?
更多相關信息,可以看一下:?WWDC 2012 session #601 – 在iOS中優化UIWebView和網站中的Web內容。
?
19) 設置陰影路徑
如果需要在view活layer中添加一個陰影,該如何處理呢?大多數開發者首先將QuartzCore框架添加到工程中,然后添加如下代碼:
上面這種方法有一個問題,Core Animation在渲染陰影效果之前,必須通過做一個離屏(offscreen)才能確定view的形狀,而這個離屏操作非常耗費資源。下面方法可以更容易地讓系統進行陰影渲染:設置陰影路徑!
通過設置陰影路徑,iOS就不用總是再計算該如何繪制陰影了。只需要使用你預先計算好的路徑即可。有一點不好的是,根據view的格式,自己可能很難計算出路徑。另外一個問題就是當view的frame改變時,必須每次都更新一下陰影路徑。
?
如果你想了解更多相關信息,可參看Mark Pospesel的一篇文章:shadowPath。
20) 優化TableView
Table views需要快速的滾動——如果不能的話,用戶會感覺到停頓。為了讓table view平滑的滾動,確保遵循了如下建議:
1.設置正確的reuseIdentifer以重用cell。
2.盡量將view設置為不透明,包括cell本身。
3.避免漸變,圖像縮放以及離屏繪制。
4.如果row的高度不相同,那么將其緩存下來。
5.如果cell顯示的內容來此網絡,那么確保這些內容是通過異步來獲取的。
6.使用shadowPath來設置陰影。
7.減少subview的數量。
8.在cellForRowAtIndexPath:中盡量做更少的操作。如果需要做一些處理,那么最好做過一次之后,就將結果緩存起來。
9.使用適當的數據結構來保存需要的信息。不同的結構會帶來不同的操作代價。
10.使用rowHeight, sectionFooterHeight 和 sectionHeaderHeight 來設置一個恒定 高度,而不要從delegate中獲取。
21) 選擇正確的數據存儲方式
選擇正確的數據存儲方式
當需要存儲和讀取大量的數據時,該如何選擇存儲方式呢?有如下選擇:
1.使用NSUserDefaults進行存儲
2.保存為XML,JSON或Plist格式的文件
3.利用NSCoding進行歸檔
4.存儲到一個本地數據庫,例如SQLite。
5.使用Core Data.
使用NSUserDefaults有什么問題呢? 雖然NSUserDefaults很好并且容易,不過只只針對于存儲小量數據(比如你的級別,或者聲音是開或關)。如果要存儲大量的數據,最好選擇別的存儲方式。
?
大量數據保存為結構化的文件也可能會帶來問題。一般,在解析這些結構數據之前,需要將內容全部加載到內存中,這是很消耗資源的。雖然可以使用SAX來處理XML文件,但是這有點復雜。另外,加載到內存中的所有對象,不一定全部都需要用到。
?
那么使用NSCoding來保存大量數據怎么樣呢?因為它同樣是對文件進行讀寫,因此依然存在上面說的問題。
?
要保存大量的數據,最好使用SQLite或Core Data。通過SQLite或Core Data可以進行具體的查詢——只需要獲取并加載需要的數據對象——避免對數據進行不合理的搜索。在性能方面,SQLite和Core Data差不大。
?
SQLite和Core Data最大的區別實際上就是用法上。Core Data代表一個對象模型,而SQLite只是一個DBMS。一般,蘋果建議使用Core Data,不過如果你有特殊的原因不能使用Core Data的話,可以使用低級別的SQLite。
?
在程序中,如果選擇使用SQLite,這里有個方便的庫FMDB?:可以利用該庫操作SQLite數據庫,而不用深入使用SQLite C API。
高級
當且僅當下面這些技巧能夠解決問題的時候,才使用它們:
22.加速啟動時間
23.使用Autorelease Pool
24.緩存圖片 — 或者不緩存
25.盡量避免Date格式化
?
高級性能提升
尋找一些高明的方法,讓自己變為一個全代碼忍者?下面這些高級的性能優化技巧可以在適當的時候讓程序盡可能的高效運行!
?
22) 加速啟動時間
能快速的啟動程序非常重要,特別是在用戶第一次啟動程序時。第一映像對程序來說非常重要!
?
讓程序盡量快速啟動的方法就是盡量以異步方式執行任務,例如網絡請求,數據訪問或解析。
?
另外,避免使用臃腫的XIBs,因為XIB的加載是在主線程中進行的。但是記住storyboard沒有這樣的問題——所以如果可以的話就使用storyboard吧!
?
注意:在利用Xcode進行調試時,watchdog不會運行,所在設備中測試程序啟動性能時,不要將設備連接到Xcode。
23) 使用Autorelease Pool
NSAutoreleasePool負責釋放一個代碼塊中的自動釋放對象。一般都是由UIKit來創建的。不過有些情況下需要手動創建NSAutoreleasePool。
?
例如,如果在代碼中創建了大量的臨時對象,你將注意到內存使用量在增加,直到這些對象被釋放。問題是只有當UIKit耗盡了 autorelease pool,這些對象才會被釋放,也就是說當不再需要這些對象之后,這些對象還在內存中占據著資源。
?
不過這個問題完全可以避免:在@autoreleasepool代碼塊中創建臨時對象,如下代碼:
當每次迭代完之后,都會釋放所有的autorelease對象。
?
關于NSAutoreleasePool的更多內容可以閱讀蘋果的官方文檔。
24) 緩存圖片--或者不緩存
iOS中從程序bundle中加載UIImage一般有兩種方法。
第一種比較常見:imageNamed。
第二種方法很少使用:imageWithContentsOfFile
?
為什么有兩種方法完成同樣的事情呢?imageNamed的優點在于可以緩存已經加載的圖片。蘋果的文檔中有如下說法:
This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.
?
這種方法會在系統緩存中根據指定的名字尋找圖片,如果找到了就返回。如果沒有在緩存中找到圖片,該方法會從指定的文件中加載圖片數據,并將其緩存起來,然后再把結果返回。
?
而imageWithContentsOfFile方法只是簡單的加載圖片,并不會將圖片緩存起來。這兩個方法的使用方法如下:
?那么該如何選擇呢?
?
如果加載一張很大的圖片,并且只使用一次,那么就不需要緩存這個圖片。這種情況imageWithContentsOfFile比較合適——系統不會浪費內存來緩存圖片。
?
然而,如果在程序中經常需要重用的圖片,那么最好是選擇imageNamed方法。這種方法可以節省出每次都從磁盤加載圖片的時間。
25) 盡量避免Date格式化
如果有許多日期需要使用NSDateFormatter,那么需要小心對待了。如之前(重用花銷很大的對象)所提到的,無論什么時候,都應該盡量重用NSDateFormatters。
?
然而,如果你需要更快的速度,那么應該使用C來直接解析日期,而不是NSDateFormatter。Sam Soffes寫了一篇文章,其中提供了一些解析ISO-8601格式日期字符的串代碼。你只需要簡單的調整一下其中的代碼就可以滿足自己特殊的需求了。
?
這聽起來不錯把——不過,你相信這還有更好的一個辦法嗎?
?
如果你自己能控制處理日期的格式,那么可以選擇 Unix timestamps(http://en.wikipedia.org/wiki/Unix_time)。Unix timestamps是一個簡單的整數,代表了從新紀元時間(epoch)開始到現在已經過了多少秒,通常這個新紀元參考時間是00:00:00 UTC on 1 January 1970。
?
你可以很容易的見這個時間戳轉換為NSDate,如下所示:
上面這個方法比C函數還要快!
?
注意:許多網絡APIs返回的時間戳都是毫秒,因此需要注意的是在將這個時間戳傳遞給dateFromUnixTimestamp之前需要除以1000。
?
何去何從?
強烈建議對程序性能優化感興趣的讀者看看下面列出來的WWDC視頻。在看視頻之前,你需要注冊一個Apple ID(注冊后就可以觀看所有WWDC2012的視頻):
#406: Adopting Automatic Reference Counting
#238: iOS App Performance: Graphics and Animations
#242: iOS App Performance: Memory
#235: iOS App Performance: Responsiveness
#409: Learning Instruments
#706: Networking Best Practices
#514: OpenGL ES Tools and Techniques
#506: Optimizing 2D Graphics and Animation Performance
#601: Optimizing Web Content in UIWebViews and Websites on iOS
#225: Up and Running: Making a Great Impression with Every Launch
下面這些視頻來自WWDC 2011?,也非常有用:
#308: Blocks and Grand Central Dispatch in Practice
#323: Introducing Automatic Reference Counting
#312: iOS Performance and Power Optimization with Instruments
#105: Polishing Your App: Tips and tricks to improve the responsiveness and performance
#121: Understanding UIKit Rendering
?
這里還有更多相關視頻,大多數來自iOS 5技術講座:
Optimizing App Performance with Instruments
Understanding iOS View Compositing
基于 “Your iOS App Performance Hitlist” 視頻,Ole Begemann寫了一篇文章。蘋果還提供了一篇非常好的文章:性能優化。其中提供的技巧和提示對程序性能提升很有幫助。
?
來源:破船的博客
by zxzhao
轉載于:https://www.cnblogs.com/ydhliphonedev/archive/2013/05/23/3095012.html
總結
以上是生活随笔為你收集整理的[转]25个增强iOS应用程序性能的提示和技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python多线程爬取斗图啦数据
- 下一篇: 【牛客网多校】19-7-25-H题 Ma