在開發iOS應用程式時,讓程式具有良好的效能是非常關鍵的。這也是使用者所期望的,如果你的程式運行遲鈍或緩慢,會招致使用者的差評。然而由於iOS裝置的局限性,有時候要想獲得良好的效能,是很困難的。在開發過程中,有許多事項需要記住,並且關於效能影響很容易就忘記。本文收集了25個關於可以提升程式效能的提示和技巧。分為3個不同的等級:初級、中級和進階:
進階
若且唯若下面這些技巧能夠解決問題的時候,才使用它們:
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代碼塊中建立臨時對象,如下代碼:
NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
@autoreleasepool {
NSError *error;
NSString *fileContents = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding error:&error];
/* Process the string, creating and autoreleasing more objects. */
}
}
當每次迭代完之後,都會釋放所有的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方法只是簡單的載入圖片,並不會將圖片緩衝起來。這兩個方法的使用方法如下:
UIImage *img = [UIImage imageNamed:@"myImage"]; // caching
// or
UIImage *img = [UIImage imageWithContentsOfFile:@"myImage"]; // no caching
那麼該如何選擇呢?
如果載入一張很大的圖片,並且只使用一次,那麼就不需要緩衝這個圖片。這種情況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,如下所示:
- (NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
上面這個方法比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寫了一篇文章。蘋果還提供了一篇非常好的文章:效能最佳化。其中提供的技巧和提示對程式效能提升很有協助。
來源:破船的部落格