iOS 效能優化套路

滴水微瀾發表於2018-11-02

***

 一級套路

***

 使用ARC管理記憶體
- 防止記憶體洩露
- 保證釋放掉不再需要的記憶體,提高效能

在正確的地方使用 reuseIdentifier
平時接觸的需要考慮重用的檢視有UICollectionView,UITableView。需要考慮它們內部的cell,header,footer。
CollectionView和TableView原理相似,內部存在著兩個容器物件,分別是:
- 當前展示檢視容器,裡面是當前展示的cell,footer,header
- 可重用檢視容器,裡面是帶有重用識別符號的cell,footer,header

儘量把View設定為完全不透明
需要將View屬性opaque設定成YES
當opaque設定成NO時,app在進行圖片展示時,會讓圖片處理器(GPU)進行影象混合計算(blending操作)。
圖片處理器會將透明View的畫素與它相臨的畫素點相加,重新計算出一個新的畫素值。如果app帶有動畫,滾動效果,效能會受到明顯的影響。

避免過於龐大的XIB
XIB是推出比較早的繪圖工具,後面在iOS5的時候推出了StoryBoard來取代XIB的地位。不過到目前它們兩個是共存的狀態,原因是它們的適用場景不同。
- XIB使用子View控制元件的定製,偏小型。但是在使用時會將整個XiB都載入到記憶體,如果XIB過大的話,會導致記憶體浪費。
- StoryBoard是偏重巨集觀的,一般做控制器跳轉,可以定義整個控制器檢視。在使用時,StoryBoard是用到哪個控制器載入哪個,不會將所有的都載入。

嚴格要求對主執行緒的使用
主執行緒是使用者對app的直接體驗,所有的互動都是靠主執行緒接受和反饋的。終於程度可見一斑。所以需要把++耗時的操作都移動到子執行緒++去,等有了結果再切換回主執行緒來。

避免在Image Views中調整圖片大小
如果給予==UIImageView==的image的尺寸不合適,那麼==UIImageView==就需要對image進行自動縮放,這個縮放操作是比較耗費資源的。對於從網路載入後需要滾動的,動畫的==UIImageView==影響更大。所以image和==UIImageView==的尺寸儘量匹配。匹配方式:

- 要求切圖尺寸符合要求
- 將獲得的圖片在本地縮放規定的尺寸後,再返回給==UIImageView==

根據業務場景選擇合適的集合(不同的資料結構)
- 陣列(增刪慢;改查快):有序集合,儲存在一段連續的記憶體空間,可方便利用下標檢視,增加刪除都會讓後序元素整體移動
- Set(增刪改查快) :無序集合,新增重複的物件會自動覆蓋掉前面的,做到整個集合只有一份
- 字典(增刪改查快):健值集合,可根據key對應操作value

合理使用gzip
在網路請求時,若資料比較大,可考慮採用壓縮格式,提高使用者體驗

***
 二級套路
***

重用view和懶載入view
- 對於重複出現的子View,考慮模仿tableview的重用機制
- 對於不一定使用的子view,考慮使用懶載入機制(懶載入是犧牲體驗提高效能)

重視快取
快取的種類很多,主要按情況來進行快取,如下所示:
- 建立麻煩而經常使用(比如NSDateFormatter和NSCalendar),對於這樣的物件快取,可以放在單例或者類屬性上。對頻繁時提供效能有大的改變。
- 請求麻煩而資源不經常改變(網路請求),
- 頻繁計算而結果不變的(tableview的行高)

圖片渲染方式選擇
- 使用UI給的切圖,渲染快,效率高。但是bundle體積大。
- 使用CoreGraphics,UIBezir曲線進行程式碼繪製,消耗效能。但是減少bundle體積

記憶體警告處理
系統提供了不少處理記憶體警告的方式,在受到記憶體經過時釋放一些可以重建的物件,可以提供app的穩定性,它們適用多種場景:
AppDelegate中的
`applicationDidReceiveMemoryWarning: `
UIViewController類中的
`didReceiveMemoryWarning`
系統提供的通知
`UIApplicationDidReceiveMemoryWarningNotification`

避免在記憶體中頻繁轉換資料結構
儘量使後臺返回的資料結構與app場景使用的一致,並選擇合適的容器儲存。
Array,Dictory,Set,根據資料使用的特性,進行合理選擇。

View背景設定的方案選擇
- 小圖平鋪
```
self.view.backgroundColor = [UIColorcolorWithPatternImage:[UIImageimageNamed:@"background"]];
```

- 全圖背景

```
BuilderUIImageView*backgroundView = [[UIImageViewalloc] initWithImage:[UIImageimageNamed:@"background"]];[self.view addSubview:backgroundView];
```

選擇適當的方式為shadowPath賦值
在開發中經常需要給View、Layer設定隱形,常見的設定方式有兩種

- 通過屬性設定

```
// Setup the shadow ...
UIView*view = [[UIViewalloc] init];
view.layer.shadowOffset=CGSizeMake(-1.0f,1.0f);
view.layer.shadowRadius =5.0f;
view.layer.shadowOpacity =0.6;
```
這種方式需要Core Animation在後臺提前根據影象frame計算出影象和陰影。增加了計算操作,消耗效能。

- 通過貝塞爾曲線賦值
```
view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];
```
由於路徑是指定好的,無需再次計算,提高了效能。

TableView優化方案
1.reuseIdentifier規範使用,cell,header,footer。
2.view的opaque為YES,避免色素計算
3.避免cell中圖片縮放
4.耗時任務子執行緒處理,避免阻塞主執行緒(網路請求,資料處理)
5.減少subviews的層級
6.用貝塞爾曲線設定陰影路徑
7.儘量避免代理賦值(tableview直接設定rowHeight, sectionFooterHeight 和 sectionHeaderHeight)
8.cell動態行高時,預先計算並儲存,提高效能

資料持久化方案
1.NSUerDefaults:相當於電腦中的偏好設定
2.plist:儲存簡單列表(城市對應的郵編列表)
3.歸檔:需要實現NSCoding協議
4.SQLite、Realm:大資料的儲存方案

***
三級套路
***

提高App啟動時間
1.非同步處理耗時任務(網路載入,資料庫訪問,批量預處理)
2.避免大規模記憶體載入(大體積xib載入)
3.主要看門狗問題

合理使用Autorelease Pool
物件過了作用域,引用計數會自動減一。如果在作用域中突然大量建物件,則記憶體會直線下降。這中情況下要適量加Autorelease Pool,進行及時釋放
合理使用圖片的載入方式
1.小體積而重複使用的圖片,用imageNamed,此時圖片物件會儲存在記憶體中
2.大體積而不長用的圖片,用imageWithContentsOfFile,圖片每次都是從本地載入。不快取

 

相關文章