1. 程式人生 > >IOS 效能優化

IOS 效能優化

最近工作比較空閒,相信我不說大家都知道效能優化的重要性了吧,很多面試公司都有的要求。這也是作為一個高階軟體開發工程師的必備技能 。

 

zero 卡頓是我們經常遇到的問題,這裡就要提到GPU/CPU了

1.為什麼會卡頓,在此期間GPU/CPU都做了哪些工作吶?

  • CPU:物件的建立/銷燬/屬性的調整/佈局計算/文字的計算和排版/圖片格式轉換和解碼,影象的繪製
  • GPU 影象處理器,主要進行紋理的渲染。(紋理是GPU所能識別的一種影象格式)
  • IOS是雙快取機制,包括前幀快取,後幀快取
  • CPU通過一系列的計算,然後GPU去渲染,通過幀快取之後被視訊控制器讀取,最後顯示到螢幕上。成像的原理是通過水平同步訊號+垂直同步訊號一幀幀的繪製而成。
  • 卡頓的原因:由於CPU要先計算-GPU渲染,假如CPU/GPU處理的事情較多,在固定的幀率下,未完成需要處理的事情,此時垂直同步訊號已經到來,兩者交叉就會造成視覺上的卡頓

2.卡頓優化

  • 儘量減少CPU/GPU的資源消耗
  • 不要頻繁的呼叫UIView的相關屬性,如frame/bounds/tranform等
  • 儘量提前計算好佈局,在有需要的時候一次性調整對應的屬性
  • 儘量吧耗時操作(文字尺寸計算/繪製,圖片解碼/繪製)放到子執行緒處理,同時我們在處理執行緒的時候要注意執行緒的最大併發數量

one  tableView的快取


1.說到快取,大家想到的是不是tableviewcell的快取機制吶
TableViewCell 複用
cellForRowAtIndexPath:

回撥的時候只建立例項,快速返回cell,不繫結資料。在willDisplayCell: forRowAtIndexPath:的時候繫結資料(賦值)。

2.TableViewCell 

tableView滑動時,會不斷呼叫heightForRowAtIndexPath:,當 cell 高度需要自適應時,每次回撥都要計算高度,會導致 UI 卡頓。為了避免重複無意義的計算,需要快取高度。

怎麼快取

  • 字典,NSCache。它可以自動清理系統佔用記憶體且是執行緒安全的。自動清理時機:往cache內新增新內容時,以及發生記憶體警告時。
  • UITableView-FDTemplateLayoutCell
    (AutoLayout佈局)
  • 快取高度可以避免無意義的計算。自適應高度的計算。推薦sunny的一篇文章

Two  記憶體問題

1.常見的問題如下:迴圈引用,webView的記憶體洩漏

在IOS 4.2 以後蘋果引用了ARC,但是ARC本質與MRC一致,都是通過引用計數管理記憶體的。但是ARC也不是萬能的。也會為了程式的正常執行,會隱式的持有或複製物件。這樣變容易造成記憶體洩漏。其中最常見的就是block的迴圈引用問題(解決方法這裡我就不多解釋了)

2.AFnetworking 的記憶體洩漏問題

使用AF的都知道,需要使用到AFHTTPSessionManager的例項物件。 [AFHTTPSessionManager manager] 我一般都是這樣獲取的,不知道你們是怎樣獲取的。但是通過Instrcument工具分析,看到他會出現記憶體洩漏。解決方法如下:

2.1 給它寫個單例

+ (AFHTTPSessionManager *)sharedHTTPSession{
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [AFHTTPSessionManager manager];
    return manager;
}

2.2 demo推薦的使用方法

@import AFNetworking;

@interface AFAppDotNetAPIClient : AFHTTPSessionManager

+ (instancetype)sharedClient;

@end

#import "AFAppDotNetAPIClient.h"

static NSString * const AFAppDotNetAPIBaseURLString = @"https://api.app.net/";

@implementation AFAppDotNetAPIClient

+ (instancetype)sharedClient {
    static AFAppDotNetAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
   _sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
       _sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    });
    
    return _sharedClient;
3.避免主執行緒堵塞

     在主執行緒中避免複雜的計算堵塞主執行緒,造成卡頓

4.圖片的處理

通常imageNamed :載入mainbundle圖片時,函式會快取載入的image。對於那麼使用較少的圖片,消耗記憶體較大 ,所以啟動圖片設定時,建議使用initWithContentsOfFile:函式。

5.  重用開銷大的物件

NSDateFormatter/NSCalendar  特別消耗記憶體,因為他們的初始化很慢。所以你可以在類中申明一個屬性或者懶載入一個他們的例項。

6.選擇合適的資料儲存

  • 使用`NSUerDefaults`-只能用來儲存小資料
  • 使用XML, JSON, 或者 plist - XML 需要讀取整個檔案到記憶體裡去解析
  • 使用NSCoding存檔- 需要讀取檔案
  • 使用類似SQLite的本地SQL資料庫
  • 使用 Core Data - 蘋果建議使用。與SQLite相比效能沒啥區別。如果使用SQLite的話建議看下Realm框架。

7.啟動時間(這個會在APP啟動優化詳細介紹)

啟動時間很重要,就像人的第一印象,避免啟動頁中使用龐大的XIB。儘量避免耗時操作,如果需要資料請求的話,儘量在子執行緒進行

8.學會處理記憶體警告

UIKit提供了幾種收集低記憶體警告的方法:

  • 在app delegate中使用`applicationDidReceiveMemoryWarning:` 的方法
  • 在你的自定義UIViewController的子類(subclass)中覆蓋`didReceiveMemoryWarning`
  • 註冊並接收 UIApplicationDidReceiveMemoryWarningNotification 的通知

在這些方法中處理,比如清掉快取,否則的話會被系統幹掉你的應用。

耗電優化

1.耗電的主要來源

  • 影象處理
  • 定位服務
  • 網路請求
  • CPU處理

2.耗電優化

  • 圖片設定圓角的時候儘量讓美工提供圖片,使用maskToBounds及layer.clipToBounds都會有很大的資源消耗
  • 一直在後臺定位重新整理位置
  • 減少定時器的使用
  • 減少I/O操作,不要頻繁寫入小資料,儘量一次讀取。讀取大資料時可以使用dispatch_io,它會優化磁碟訪問。資料量較大時,建議使用資料庫。
  • 網路優化:減少網路請求的次數,如果資料多次都是相同建議使用快取。使用斷點續傳下載資料。讓使用者取消長時間執行或者網路慢的網路操作,設定合適的網路超時時間。