1. 程式人生 > >iOS效能調優(全)---記憶體優化和UI優化

iOS效能調優(全)---記憶體優化和UI優化

iOS應用效能調優的25個建議和技巧

本文來自iOSTutorial Team  Marcelo Fabri,他是Movile的一名 iOS 程式設計師。這是他的個人網站:,你還可以在Twitter上關注

效能對 iOS 應用的開發尤其重要,如果你的應用失去反應或者很慢,失望的使用者會把他們的失望寫滿AppStore的評論。然而由於iOS裝置的限制,有時搞好效能是一件難事。開發過程中你會有很多需要注意的事項,你也很容易在做出選擇時忘記考慮效能影響。

這正是我寫下這篇文章的原因。這篇文章以一個方便檢視的核對錶的形式整合了你可以用來提升你app效能的25條建議和技巧。

請耐心讀完這篇文章,為你未來的

app提個速!

注意:每在優化程式碼之前,你都要注意一個問題,不要養成預優化程式碼的錯誤習慣。時常使用Instrumentsprofile你的程式碼來發現需要提升的方面。MattGalloway寫過一篇很棒的如何利用Instruments

還要注意的是,這裡列出的其中一些建議是有代價的,所建議的方式會提升app的速度或者使它更加高效,但也可能需要花很多功夫去應用或者使程式碼變得更加複雜,所以要仔細選擇。

目錄

我要給出的建議將分為三個不同的等級:入門級、中級和進階級:

入門級(這是些你一定會經常用在你app開發中的建議)

·      1. ARC管理記憶體

·      

2. 在正確的地方使用reuseIdentifier

·      3. 儘可能使Views透明

·      4. 避免龐大的XIB

·      5. 不要block主執行緒

·      6. ImageViews中調整圖片大小

·      7. 選擇正確的Collection

·      8. 開啟gzip壓縮

中級(這些是你可能在一些相對複雜情況下可能用到的)

·      9. 重用和延遲載入Views

·      10. Cache, Cache, 還是Cache

·      11. 權衡渲染方法

·      12. 處理記憶體警告

·      

13. 重用大開銷的物件

·      14. 使用SpriteSheets

·      15. 避免反覆處理資料

·      16. 選擇正確的資料格式

·      17. 正確地設定BackgroundImages

·      18. 減少使用Web特性

·      19. 設定ShadowPath

·      20. 優化你的TableView

·      21. 選擇正確的資料儲存選項

進階級(這些建議只應該在你確信他們可以解決問題和得心應手的情況下采用)

·      22. 加速啟動時間

·      23. 使用AutoreleasePool

·      24. 選擇是否快取圖片

·      25. 儘量避免日期格式轉換

無需贅述,讓我們進入正題吧~

初學者效能提升

這個部分致力於一些能提高效能的基本改變。但所有層次的開發者都有可能會從這個記錄了一些被忽視的專案的小小的效能備忘錄裡獲得一些提升。

1. ARC管理記憶體

ARC(AutomaticReference Counting, 自動引用計數)iOS5一起釋出,它避免了最常見的也就是經常是由於我們忘記釋放記憶體所造成的記憶體洩露。它自動為你管理retainrelease的過程,所以你就不必去手動干預了。

下面是你會經常用來去建立一個View的程式碼段:

1

2

3

4

UIView *view = [[UIView alloc] init];

// ...

 [self.view addSubview:view];

 [view release];

忘掉程式碼段結尾的release簡直像記得吃飯一樣簡單。而ARC會自動在底層為你做這些工作。

除了幫你避免記憶體洩露,ARC還可以幫你提高效能,它能保證釋放掉不再需要的物件的記憶體。這都啥年代了,你應該在你的所有專案裡使用ARC!

這裡有一些更多關於ARC的學習資源:

·      If you still arent convinced of the benefits of ARC, check outthis article on  to really convince you whyyou should be using it!

ARC當然不能為你排除所有記憶體洩露的可能性。由於阻塞,retain 週期管理不完善的CoreFoundationobject(還有C結構)或者就是程式碼太爛依然能導致記憶體洩露。

這裡有一篇很棒的介紹ARC不能做到以及我們該怎麼做的文章http://conradstoll.com/blog/2013/1/19/blocks-operations-and-retain-cycles.html

2. 在正確的地方使用 reuseIdentifier

一個開發中常見的錯誤就是沒有給UITableViewCellsUICollectionViewCells,甚至是UITableViewHeaderFooterViews設定正確的reuseIdentifier

為了效能最優化,tableview `tableView:cellForRowAtIndexPath:` rows分配cells的時候,它的資料應該重用自UITableViewCell一個tableview維持一個佇列的資料可重用的UITableViewCell物件。

不使用reuseIdentifier的話,每顯示一行tableview就不得不設定全新的cell。這對效能的影響可是相當大的,尤其會使app的滾動體驗大打折扣。

iOS6起,除了UICollectionViewcells和補充views,你也應該在headerfooterviews中使用reuseIdentifiers

想要使用reuseIdentifiers的話,在一個tableview中新增一個新的cell時在data sourceobject中新增這個方法:

1

2

staticNSString *CellIdentifier = @"Cell";

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

這個方法把那些已經存在的cell從佇列中排除,或者在必要時使用先前註冊的nib或者class創造新的cell。如果沒有可重用的cell,你也沒有註冊一個class或者nib的話,這個方法返回nil

3.儘量把views設定為透明

如果你有透明的Views你應該設定它們的opaque屬性為YES

原因是這會使系統用一個最優的方式渲染這些views。這個簡單的屬性在IB或者程式碼裡都可以設定。

Apple的文件對於為圖片設定透明屬性的描述是:

(opaque)這個屬性給渲染系統提供了一個如何處理這個view的提示。如果設為YES渲染系統就認為這個view是完全不透明的,這使得渲染系統優化一些渲染過程和提高效能。如果設定為NO,渲染系統正常地和其它內容組成這個View。預設值是YES

在相對比較靜止的畫面中,設定這個屬性不會有太大影響。然而當這個view嵌在scrollview裡邊,或者是一個複雜動畫的一部分,不設定這個屬性的話會在很大程度上影響app的效能。

你可以在模擬器中用Debug\ColorBlended Layers選項來發現哪些view沒有被設定為opaque。目標就是,能設為opaque的就全設為opaque!

4. 避免過於龐大的XIB

iOS5中加入的Storyboards(分鏡)正在快速取代XIB。然而XIB在一些場景中仍然很有用。比如你的app需要適應iOS5之前的裝置,或者你有一個自定義的可重用的view,你就不可避免地要用到他們。

如果你不得不XIB的話,使他們儘量簡單。嘗試為每個Controller配置一個單獨的XIB,儘可能把一個ViewControllerview層次結構分散到單獨的XIB中去。

需要注意的是,當你載入一個XIB的時候所有內容都被放在了記憶體裡,包括任何圖片。如果有一個不會即刻用到的view,你這就是在浪費寶貴的記憶體資源了。Storyboards就是另一碼事兒了,storyboard僅在需要時例項化一個viewcontroller.

當家在XIB是,所有圖片都被chache,如果你在做OS X開發的話,聲音檔案也是。Apple相關文件中的記述是:

當你載入一個引用了圖片或者聲音資源的nib時,nib載入程式碼會把圖片和聲音檔案寫進記憶體。在OS X中,圖片和聲音資源被快取在namedcache中以便將來用到時獲取。在iOS中,僅圖片資源會被存進namedcaches。取決於你所在的平臺,使用NSImage UIImage`imageNamed:`方法來獲取圖片資源。

很明顯,同樣的事情也發生在storyboards中,但我並沒有找到任何支援這個結論的文件。如果你瞭解這個操作,寫信給我!

想要了解更多關於storyboards的內容的話你可以看看Matthijs HollemansBeginning Storyboards in iOS 5 Part 1Part 2

5. 不要阻塞主執行緒

永遠不要使主執行緒承擔過多。因為UIKit在主執行緒上做所有工作,渲染,管理觸控反應,迴應輸入等都需要在它上面完成。

一直使用主執行緒的風險就是如果你的程式碼真的block了主執行緒,你的app會失去反應。這。。。正是在AppStore中拿到一顆星的捷徑 :]

大部分阻礙主程序的情形是你的app在做一些牽涉到讀寫外部資源的I/O操作,比如儲存或者網路。

你可以使用`NSURLConnection`非同步地做網路操作:
+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue*)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler

或者使用像這樣的框架來非同步地做這些操作。

如果你需要做其它型別的需要耗費巨大資源的操作(比如時間敏感的計算或者儲存讀寫)那就用 GrandCentral Dispatch,或者 NSOperation NSOperationQueues.

下面程式碼是使用GCD的模板

1

2

3

4

5

6

7

8

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// switch to a background thread and perform your expensive operation

    dispatch_async(dispatch_get_main_queue(), ^{

// switch back to the main thread to update your UI

    });

});

發現程式碼中有一個巢狀的`dispatch_async`嗎?這是因為任何UIKit相關的程式碼需要在主執行緒上進行。

6. Image Views中調整圖片大小

如果要在`UIImageView`中顯示一個來自bundle的圖片,你應保證圖片的大小和UIImageView的大小相同。在執行中縮放圖片是很耗費資源的,特別是`UIImageView`巢狀在`UIScrollView`中的情況下。

如果圖片是從遠端服務載入的你不能控制圖片大小,比如在下載前調整到合適大小的話,你可以在下載完成後,最好是用backgroundthread,縮放一次,然後在UIImageView中使用縮放後的圖片。

7. 選擇正確的Collection

學會選擇對業務場景最合適的類或者物件是寫出能效高的程式碼的基礎。當處理collections時這句話尤其正確。

Apple有一個的文件詳盡介紹了可用的classes間的差別和你該在哪些場景中使用它們。這對於任何使用collections的人來說是一個必讀的文件。

呵呵,我就知道你因為太長沒看這是一些常見collection的總結:

·      Arrays: 有序的一組值。使用indexlookup很快,使用valuelookup很慢,插入/刪除很慢。

·      Dictionaries: 儲存鍵值對。用鍵來查詢比較快。

·      Sets: 無序的一組值。用值來查詢很快,插入/刪除很快。

8. 開啟gzip壓縮

大量app依賴於遠端資源和第三方API,你可能會開發一個需要從遠端下載XML,JSON, HTML或者其它格式的app

問題是我們的目標是移動裝置,因此你就不能指望網路狀況有多好。一個使用者現在還在edge網路,下一分鐘可能就切換到了3G。不論什麼場景,你肯定不想讓你的使用者等太長時間。

減小文件的一個方式就是在服務端和你的app中開啟gzip。這對於文字這種能有更高壓縮率的資料來說會有更顯著的效用。

好訊息是,iOS已經在NSURLConnection中預設支援了gzip壓縮,當然AFNetworking這些基於它的框架亦然。像GoogleApp Engine這些雲服務提供者也已經支援了壓縮輸出。

如果你不知道如何利用Apache或者IIS(伺服器)來開啟gzip,可以讀下這篇文章

中級效能提升

你確信你已經掌握了前述那些基礎級的優化方案了嗎?但實際情況是,有時一些解決方案並不像那些一樣明顯,它們往往嚴重依賴於你如何架構和書寫你的app。下面的這些建議就是針對這些場景的。

9. 重用和延遲載入(lazy load) Views

更多的view意味著更多的渲染,也就是更多的CPU和記憶體消耗,對於那種嵌套了很多viewUIScrollView裡邊的app更是如此。

這裡我們用到的技巧就是模仿`UITableView``UICollectionView`的操作不要一次建立所有的subview,而是當需要時才建立,當它們完成了使命,把他們放進一個可重用的佇列中。

這樣的話你就只需要在滾動發生時建立你的views,避免了不划算的記憶體分配。

建立views的能效問題也適用於你app的其它方面。想象一下一個使用者點選一個按鈕的時候需要呈現一個view的場景。有兩種實現方法:

·      1. 建立並隱藏這個view當這個screen載入的時候,當需要時顯示它;

·      2. 當需要時才建立並展示。

每個方案都有其優缺點。

用第一種方案的話因為你需要一開始就建立一個view並保持它直到不再使用,這就會更加消耗記憶體。然而這也會使你的app操作更敏感因為當用戶點選按鈕的時候它只需要改變一下這個view的可見性。

第二種方案則相反-消耗更少記憶體,但是會在點選按鈕的時候比第一種稍顯示卡頓。

10. Cache, Cache, 還是Cache!

一個極好的原則就是,快取所需要的,也就是那些不大可能改變但是需要經常讀取的東西。

我們能快取些什麼呢?一些選項是,遠端伺服器的響應,圖片,甚至計算結果,比如UITableView的行高。

NSURLConnection預設會快取資源在記憶體或者儲存中根據它所載入的HTTPHeaders。你甚至可以手動建立一個NSURLRequest然後使它只加載快取的值。

下面是一個可用的程式碼段,你可以可以用它去為一個基本不會改變的圖片建立一個NSURLRequest並快取它:

1

2

3

4

5

6

7

8

9

10

+ (NSMutableURLRequest *)imageRequestWithURL:(NSURL *)url {

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;// this will make sure the request always returns the cached image

    request.HTTPShouldHandleCookies = NO;

    request.HTTPShouldUsePipelining = YES;

    [request addValue:@"image/*"forHTTPHeaderField:@"Accept"];

returnrequest;

}

注意你可以通過

相關推薦

iOS效能調()---記憶體優化UI優化

iOS應用效能調優的25個建議和技巧 本文來自iOSTutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程式設計師。這是他的個人網站:,你還可以在Twitter上關注。 效能對 iOS 應用的開發尤其重要,如果你

IOS效能調系列:使用Instruments動態分析記憶體洩漏,調instruments

第一篇介紹了Analyze對App做靜態分析,可以發現應用中的記憶體洩漏問題,對於有些記憶體洩漏情況通過靜態分析無法解決的,可以通過動態分析來發現,分析起來更有針對性。 從本篇開始介紹XCode提供的強大的分析工具Instruments,記憶體分析只是Instruments中的一個功能,其他功能後續介紹

SAP CDS view效能調的一些準則例子

SAP CDS view優化的guideline: 一個很簡單的SELECT CDS view的open sql: 它的execution plan都會非常複雜: 我們就只展開上面execution plan tree最左邊的節點:展開之後要幾個螢幕才能顯示的下: 效能提升

GitLab效能調-佔用記憶體過大的問題

開發十年,就只剩下這套架構體系了! >>>   

mysql效能調筆記(二)--查詢優化索引

一、Mysql執行查詢流程                                                                           mysql執行查詢的流程 mysql執行查詢內部路程:1.客服端傳送一條查詢給伺服器

spark效能調(四)調節堆外記憶體等待時長

調節堆外記憶體!!! executor堆外記憶體 spark底層shuffle使用netty傳輸,所以使用了堆外記憶體!1.2之前是NIO就是socket,之後預設使用netty 有時候,如果你的spark作業處理的資料量特別特別大,幾億資料量;然後spark作業一執行,時

iOS應用效能調的25個建議技巧

效能對 iOS 應用的開發尤其重要,如果你的應用失去反應或者很慢,失望的使用者會把他們的失望寫滿App Store的評論。然而由於iOS裝置的限制,有時搞好效能是一件難事。開發過程中你會有很多需要注意的事項,你也很容易在做出選擇時忘記考慮效能影響。 這正是我寫下這篇文章的原

JVM效能調(1) —— JVM記憶體模型類載入執行機制

一、JVM記憶體模型 執行一個 Java 應用程式,必須要先安裝 JDK 或者 JRE 包。因為 Java 應用在編譯後會變成位元組碼,通過位元組碼執行在 JVM 中,而 JVM 是 JRE 的核心組成部分。JVM 不僅承擔了 Java 位元組碼的分析和執行,同時也內建了自動記憶體分配管理機制。這個機制可以大

Nginx效能調之快取記憶體

Nginx可以快取一些檔案(一般是靜態檔案),減少Nginx與後端伺服器的IO,提高使用者訪問速度。而且當後端伺服器宕機時,Nginx伺服器能給出相應的快取檔案響應相關的使用者請求。 一 Nginx靜態快取基本配置 在tomcat的webapps目錄下建立hello.html,內容

網站高併發優化效能調總結

最近在對PHP網站高併發高效能有所領悟,今天寫一篇關於這方面的文章。今天用我的測試站點:http://zhimo.yuanzhumuban.cc/來講解例項。 支模網整體開發到上線為10個月左右,後端採用php開源框架destoon,站點總資料為800萬,其中每天會更新入庫資料5000-50000資料不等,

雲端計算生產環境架構效能調遷移套路總結(以 AWS 為例)

最近完成了一個雲端計算平臺應用的架構調優。客戶是一個 Wordpress + MySQL 的站點,剛從本地資料中心遷移到了 AWS,由於團隊技能限制,無法充分發揮雲端計算的優勢。加之應用程式在夜間高流量時段崩潰,架構優化和遷移迫在眉睫。本文以這次架構遷移經驗為例,介紹雲端計算架構優化遷移的基本步驟和

jvm工具介紹效能調

jvm工具 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/ Jps Jstat Jinfo Jmap Jhat Jstack JConsole Jps (Java p

MySQL效能優化總結___本文乃《MySQL效能調與架構設計》讀書筆記!

一、MySQL的主要適用場景 1、Web網站系統 2、日誌記錄系統 3、資料倉庫系統 4、嵌入式系統 二、MySQL架構圖:   三、MySQL儲存引擎概述 1)MyISAM儲存引擎 MyISAM儲存引擎的表在資料庫中,每一個表

[jvm]五tomcat效能調效能監控(visualvm)

1、JDK記憶體優化 根據伺服器物理內容情況配置相關引數優化tomcat效能。當應用程式需要的記憶體超出堆的最大值時虛擬機器就會提示記憶體溢位,並且導致應用服務崩潰。因此一般建議堆的最大值設定為可用記憶體的最大值的80%。 Tomcat預設可以使用的記憶體為128MB,在較大型的應用專案中,

Linux工具效能調系列二:buffercache

一,案例入門 我們來看一個例子,我們來看free輸出,free採集資料來源是:/proc/meminfo檔案,對於這個檔案,會貫穿這個系列。 [email protected]:~# free total used free sh

效能調之MySQL篇三:MySQL配置定位以及優化

1、優化方式 一般的優化方法有:硬體優化,配置優化,sql優化,表結構優化。下面僅僅介紹配置優化,具體優化設定可以參考本人另外一篇部落格,傳送門:https://www.cnblogs.com/langhuagungun/p/9507206.html 2、mysql配置分析 1)常見瓶頸 90%系統瓶

效能調之MySQL篇四:MySQL配置定位以及優化

一、CPU最大效能模式 cpu利用特點 5.1 最高可用4個核 5.5 最高可用24核 5.6 最高可用64核心 一次query對應一個邏輯CPU 你仔細檢查的話,有些伺服器上會有的一個有趣的現象:你cat /proc/cpuinfo時,會發現CPU的頻率竟然跟它標

JVM記憶體管理及JAVA效能調相關筆記

JVM篇 1.JVM記憶體分配:方法區、Java棧、本地方法棧、堆、程式計數器。方法區:在方法區中,儲存了每個類的資訊(包括類的名稱、方法資訊、欄位資訊)、靜態變數、常量以及編譯器編譯後的程式碼等。Java棧:用來儲存方法中的區域性變數(包括在方法中宣告的非靜態變數以及函式形參)。對於基本資料型別的

Spark效能調---fastutil優化資料格式

Spark中應用fastutil的場景: 1、如果運算元函式使用了外部變數;那麼第一,你可以使用Broadcast廣播變數優化;第二,可以使用Kryo序列化類庫,提升序列化效能和效率;第三,如果外部變數是某種比較大的集合,那麼可以考慮使用fastutil改寫外部變數,首先從源頭上就減少記憶體的佔

轉【Zabbix效能調:配置優化

轉載:https://sre.ink/zabbix-turn-conf/ #通過日誌可以分析當前服務狀態。LogFile=/tmp/zabbix_server.log #日誌檔案路徑。LogFileSize=1 #日誌檔案最大值(MB),超過則滾動,設為0表示不回滾。DebugLevel=3 #除錯日誌級別