iOS 项目优化
前言
近期正處于一段工作空白區,也想著學習學習一下項目優化,所以就自己的項目出手,一步一步地優化項目。
一、項目結構與應用包瘦身
項目結構
項目本身首先劃分功能區以Page、Core、App劃分
- Page存儲應用的模塊,包含首頁、個人中心等,每個模塊下再以Controller、View、Model劃分
- Core 存儲著一些與項目業務、界面無關的類,包括分類、宏定義、封裝的請求基類等
- App則存儲著一些與項目相關的類,包括API、Base基類等
應用包瘦身
1、首先找出項目中未使用的圖片:
這里使用了python腳本 腳本地址 找出項目中未使用的圖片,結果不是非常準確,但是可以自行判斷(存在圖片使用是根據服務端返回顯示的情況等)
使用方法:
后面發現 這個工具 您可以試試
2、圖片無損壓縮
這里使用工具 ImageOptim ,點擊鏈接下載 將項目圖片拖入優化即可 優化結果:
3、代碼瘦身
這里推薦使用LinkMap,可以知道項目中各個類的大小,以權衡是否有替換方案
4、 使用 fui 找到應用中未使用的類
安裝fui
sudo gem install fui -n /usr/local/bin 復制代碼到項目中使用
fui find 復制代碼即可找出未引用的類,自行判斷刪除即可 #####優化前與優化后的ipa包大小對比
二、項目性能優化
內存
使用instruments leaks 檢測 打開:
卡頓
在性能優化中一個最具參考價值的屬性是FPS:全稱Frames Per Second,其實就是屏幕刷新率,蘋果的iphone推薦的刷新率是60Hz,也就是說GPU每秒鐘刷新屏幕60次,這每刷新一次就是一幀frame,FPS也就是每秒鐘刷新多少幀畫面。靜止不變的頁面FPS值是0,這個值是沒有參考意義的,只有當頁面在執行動畫或者滑動的時候,FPS值才具有參考價值,FPS值的大小體現了頁面的流暢程度高低,當低于45的時候卡頓會比較明顯。
這里使用Core Animation來檢測,注:需使用真機
打開: 1、Product -> Profile -> Core Animation 2、啟動應用 3、滑動查看FPS值
卡頓優化:1、Color Blended Layers (圖層混合)
這個選項是檢測哪里發生了圖層混合,先介紹一下什么是圖層混合?很多情況下,界面都是會出現多個UI控件疊加的情況,如果有透明或者半透明的控件,那么GPU會去計算這些這些layer最終的顯示的顏色,也就是我們肉眼所看到的效果。例如一個上層Veiw顏色是綠色RGB(0,255,0),下層又放了一個View顏色是紅色RGB(0,0,255),透明度是50%,那么最終顯示到我們眼前的顏色是藍色RGB(0,127.5,127.5)。這個計算過程會消耗一定的GPU資源損耗性能。如果我們把上層的綠色View改為不透明, 那么GPU就不用耗費資源計算,直接顯示綠色。 如果出現圖層混合了,打開Color Blended Layers選項,那塊區域會顯示紅色,所以我們調試的目的就是將紅色區域消減的越少越好。那么如何減少紅色區域的出現呢?只要設置控件不透明即可。
eg:
運行應用 在模擬器中找到:
顯示運行后的界面: 出現了許多混合圖層,我們就是要消除這些紅色TIP:當UILabel的內容是中文,需要添加一句 label.layer.masksToBounds = YES,因為當UILabel的內容為中文時,label實際渲染區域要大于label的size,最外層多了一個sublayer,如果不設置第二行label的邊緣外層灰出現圖層混合的紅色,因此需要在label內容是中文的情況下加第二句。單獨使用label.layer.masksToBounds = YES是不會發生離屏渲染的
注:xib 也可以直接設置 masksToBounds 在控件的:
點擊+號添加 layer.masksToBounds 打鉤即可 優化后的界面: 相比之前,清爽了不少,圖片還需美工提供的圖片為無透明的圖片。2、Color Misaligned Images(圖片大小)
這個選項可以幫助我們查看圖片大小是否正確顯示。如果image size和imageView size不匹配,image會出現黃色。要盡可能的減少黃色的出現,因為image size與imageView size不匹配,會消耗資源壓縮圖片。 選擇:
如果圖片出現黃色,可自行將圖片壓縮至ImageView大小3、Color Offscreen-Rendered Yellow(離屏渲染)
離屏渲染Off-Screen Rendering 指的是GPU在當前屏幕緩沖區以外新開辟一個緩沖區進行渲染操作。還有另外一種屏幕渲染方式-當前屏幕渲染On-Screen Rendering ,指的是GPU的渲染操作是在當前用于顯示的屏幕緩沖區中進行。 離屏渲染會先在屏幕外創建新緩沖區,離屏渲染結束后,再從離屏切到當前屏幕, 把離屏的渲染結果顯示到當前屏幕上,這個上下文切換的過程是非常消耗性能的,實際開發中盡可能避免離屏渲染。 觸發離屏渲染Offscreen rendering的行為:
- drawRect:方法
- layer.shadow
- layer.allowsGroupOpacity or layer.allowsEdgeAntialiasing
- layer.shouldRasterize
- layer.mask
- layer.masksToBounds && layer.cornerRadius
eg:
運行項目,打開:
項目中,此處顯示黃色:在切圓角時,使用了layer.masksToBounds && layer.cornerRadius 這里我們換一種實現方式,使用貝塞爾曲線畫一個邊框Layer覆蓋在上面即解決了離屏渲染
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];CAShapeLayer *strokeLayer = [CAShapeLayer layer];strokeLayer.path = maskPath.CGPath;strokeLayer.fillColor = [UIColor clearColor].CGColor; //內容填充的顏色設置為clearstrokeLayer.strokeColor = kWhiteColor.CGColor; //邊色strokeLayer.lineWidth = 1; // 邊寬[self.layer addSublayer:strokeLayer]; 復制代碼網上還有許多方式可以設置圓角:
優化后的FPS
三、使用RunTime 盡量避免 crash
程序運行中難免會出現崩潰,這里我們可以使用runtime盡量避免一些常見的崩潰錯誤: #####eg: 給NSArray 替換 objectAtIndex:方法
+ (void)load {[NSClassFromString(@"__NSArrayI") swapMethod:@selector(objectAtIndex:) currentMethod:@selector(mq_objectAtIndex:)]; }- (id)mq_objectAtIndex:(NSUInteger)index {if (index >= [self count]){return nil;}return [self mq_objectAtIndex:index]; }+ (void)swapMethod:(SEL)originMethod currentMethod:(SEL)currentMethod; {Method firstMethod = class_getInstanceMethod(self, originMethod);Method secondMethod = class_getInstanceMethod(self, currentMethod);method_exchangeImplementations(firstMethod, secondMethod); } 復制代碼Load方法替換 objectAtIndex 為 mq_objectAtIndex ,當調用objectAtIndex時會走到mq_objectAtIndex,判斷是否越界,以此來預防數組越界的crash 其他類像NSDictionary、NSString也可以自行添加
結語
iOS項目優化還有挺多方面的,包括電池優化、啟動優化等等,筆者這里就先優化到這里,如果有需求需要優化的話,會再進行更新,謝謝支持!
轉載于:https://juejin.im/post/5cf8cef85188255f0a4e0bc8
總結
- 上一篇: Python3之paramiko模块
- 下一篇: #define定义宏函数 的正确使用