目錄
前言
一、安裝包組成
二、資源瘦身優化
2.1 無用資源洗掉
2.2 資源壓縮
2.3 圖片管理方式
2.4 動態下載資源
三、可執行檔案優化
3.1 找到方法和類的全集:Link Map 檔案分析
3.2 找到已使用的方法和類: Mach-O 檔案
3.3 使用AppCode
四、編譯選項優化
總結
前言
隨著版本迭代和業務的堆積,安裝包會越來越大,安裝包變大也帶來了其他隱患,比如之前在App Store下載的應用超過150MB時,是無法使用流量下載的,只能連接到無線局域網下載,雖然現在可以設定允許所有App使用蜂窩資料下載,但是有個“超過200MB時請求許可”的選項可能是默認勾選的,而且對流量和手機存盤空間敏感的用戶,有時候安裝包的大小就決定了是否擁有這個用戶,所以,對于安裝包的瘦身是App發展和優化程序中不可避免的重要一步,
一、安裝包組成
iOS的安裝包就是ipa,把一個ipa檔案將后綴.ipa修改為.zip,然后將其解壓出來,在Payload中的.app 選擇顯示包內容,就可以查看里面的資源檔案,
.app 里面的主要內容
-
_CodeSignature:存放檔案的 hash 串列,里面有一個檔案 CodeResources ,這個檔案是一個屬性串列,包含 bundle 中所有其他檔案的串列,這個屬性串列只有一項 files,這是一個字典,鍵是檔案名,值通常是 Base64 格式的散列值,如果鍵表示的檔案是可選的,那么值本身也是一個字典,這個字典有一個 hash 鍵和一個 optional 鍵(布林值 true),它的作用是用來判斷一個應用程式是否完好無損,能夠防止不小心修改或損懷澩檔案,

- 一些.bundle檔案:bundle是一種標準化的層次結構,保存了可執行代碼以及代碼所需要的資源,bundle檔案可以理解為一個資源包,用于存盤圖片、音頻、文本、nib檔案等,方便在其他專案中參考包內的資源,bundle包是靜態的,不參與編譯,也就意味著,bundle 包中不能包含可執行的檔案,它僅僅是作為資源,被決議成為特定的二進制資料,從.app的包里可以看到,.bundle檔案基本上都是一些SDK制作的,
- Assets.car:把放在Assets.xcassets中的圖片(除了AppIcon和LaunchImage,這兩種圖片是直接放在包中的)打包后統一壓縮成一個Assets.car的檔案,減小包的大小,
- 一些.nib檔案:使用xib創建的檔案,
- .plist:一些屬性串列檔案,
- Frameworks:Framework 是一種打包方式,將庫的二進制檔案,頭檔案和有關的資源檔案打包到一起,方便管理和分發,
- 一些.png、.jpg、.mp3、.mp4等形式的圖片和音視瞥澩,
二、資源瘦身優化
資源瘦身主要是去掉無用資源和壓縮資源,資源包括圖片、音視頻檔案、組態檔等,其中圖片資源應該是用的最多的,無用資源是指資源在工程檔案里,但沒有被代碼參考,
2.1 無用資源洗掉
相關業務或模塊移除后,對應的圖片資源沒有洗掉,造成安裝包里面積累很多無用圖片,清理的辦法也比較簡單,就是根據圖片的名字在Xcode里全域搜索,如果沒有搜到可能就是沒有用到的圖片,但是并不完全肯定,也有代碼里有可能是通過字串拼接的方式使用了圖片,
查找并洗掉這些無用的圖片資源流程是這樣的
- 查找:使用find命令獲取選定的目錄下的所有指定型別的資源檔案(比如png、jpg、gif等),
- 匹配:使用正則匹配在代碼中使用到的圖片名,可以設定匹配規則,比如為了方便回圈創建,這樣命名的@"icon_%d",
- 洗掉:所有的資源檔案減去用到的資源檔案就是無用的資源檔案了,對這些無用的資源再確認一下洗掉就可以了,
推薦一個好用的開源工具 LSUnusedResources,使用起來很簡單,搜索速度和匹配的準確性也很高,
除了圖片資源外,音視瞥澩,像.json、plist、README.md 等這樣的無用檔案也可以洗掉掉,
2.2 資源壓縮
對于有用的資源檔案,可以通過無損壓縮減少占用空間,盡量使用8-bit的PNG圖片,比32-bit的圖片能減少4倍的壓縮率,由于8-bit的圖片支持最多256種不同的顏色,所以8-bit的圖片一般只應該用于一小部分的顏色圖片,例如灰度圖片最好使用8-bit,
2.3 圖片管理方式
工程中的圖片資源主要有兩個方式管理,一種是在專案中添加檔案夾存放,另一種是放在Assets.xcassets管理,推薦使用Assets.xcassets管理,因為它會把里邊的所有 png 格式的圖片打包成一個Assets.car檔案,壓縮比率比檔案夾管理圖片要高,而且可以根據不同的設備,不同的解析度設定相應的圖片,
2.4 動態下載資源
有些非必要的檔案資源可以放在服務器,結合本地快取策略,比如主題、皮膚、音樂這樣的資源,
三、可執行檔案優化
App 安裝包主要是由資源檔案和可執行檔案(Mach-O)組成的,可執行檔案大小是由代碼量決定的,通常情況下,對可執行檔案進行瘦身,就是找到并洗掉無用代碼的程序,方法和圖片資源清理類似:先找出方法和類的全集,再找到使用過的方法和類,取二者的差集就得到無用代碼,人工二次確認后洗掉,
3.1 找到方法和類的全集:Link Map 檔案分析
Xcode build產生的Link Map檔案能比較直觀的反映出程式各部分的檔案大小情況,對于減少包體積很有幫助,
獲取 LinkMap :將 Build Setting 里的 Write Link Map File 設定為 Yes,然后指定 Path to Link Map File 的路徑就可以得到每次編譯后的 LinkMap 檔案了,我們只修改一下生成的 Link Map檔案的路徑就可以了,后綴名不要修改,

LinkMap 檔案分為三部分:Object files、Section 和 Symbols,
- Object files:代碼工程中所有檔案編譯后的目標檔案.o;

- Section:描述了代碼段在生成的 Mach-O 里的偏移位置和大小,包括代碼段(__TEXT)和資料段(__DATA)的分布情況;

- Symbols:符號相關資訊,會列出每個方法、類、block,以及它們的大小,第一列Address 是在檔案中的偏移位置,第二列Size 是大小,第三列File 是對應上面Object files
中的檔案編號,第四列Name 是檔案名,可以看到黃色框框部分跟上圖Object files 是對應的,
通過對 LinkMap 的分析,我們不但可以統計出所有的方法和類,還能夠清晰地看到代碼所占包大小的具體分布,從而有針對性地對代碼進行優化,對Symbols的分析還可以通過方法的二進制重排來提升冷啟動速度(本篇不做過多介紹),
3.2 找到已使用的方法和類: Mach-O 檔案
Mach-O是Mach Object的縮寫,是Mac/iOS上用于存盤程式、庫的標準格式,常見的Mach-O檔案比如iOS開發好的代碼打包好后就是Mach-O格式的檔案,???Xcode編譯完工程會生成一個可執行程式,查找方式也簡單,首先在Xcode的Preferences里找到這個路徑:

在這個檔案夾下找到對應的工程檔案名/Build/Products/Debug,進入這個目錄下,就可以找到我們的可執行檔案了,

iOS 的方法都會通過 objc_msgSend 來呼叫,而objc_msgSend 在 Mach-O 檔案里是通過 __objc_selrefs 這個 section 來獲取 selector 這個引數的,所以,__objc_selrefs 里是被呼叫了的方法,__objc_classrefs 里是被呼叫過的類,__objc_superrefs 是呼叫過 super 的類,通過 __objc_classrefs 和 __objc_superrefs,我們就可以找出使用過的類和子類,可以通過MachOView來查看 Mach-O 檔案里的資訊,

對比Link Map檔案就可以找出沒有用到的類和方法了,但是Objective-C 是動態語言,方法可以在運行時動態呼叫,通過這種方法找到的無用代碼還需人工確認才可以洗掉,
3.3 使用AppCode
如果不想這么麻煩地去分析對比,推薦一個好用的工具 AppCode,代碼量不是很大時,AppCode通過靜態分析可以快速幫我們找出沒有用到的檔案和方法,使用方式是在 AppCode 里選擇 Code->Inspect Code 就可以進行靜態分析,

分析結果也是清晰明了,包括:
Not implemented methods:沒有實作的方法;
Key value coding:KVC相關,比如使用KVC訪問了@private修飾的成員變數;
Unused class:沒有用到的類;
Unused import statement:無用類引入宣告;
Unused instance variable :無用的實體變數;
Unused method:沒有用到的方法;
Unused property :沒有用到的屬性;
Unused parameter :無用引數;
Unused local variable :無用的區域變數;
Unused value :無用的值;
Unused macro :無用的宏;
Unused global declaration :無用全域宣告,

但是檢測結果并不是完全可靠,只是為我們優化代碼提供參考方向,最好還是人工確認一下,不要完全相信工具,
四、編譯選項優化
Xcode 支持編譯器層面的一些優化優化選項,可以讓我們在更快的編譯速度、更小的二進制和更快的執行速度之間自由選擇想要的優化程度,
- Strip Linked Product、Make Strings Read-Only、Symbols Hidden by Default設定為YES,目前Xcode已經默認打開的,老專案注意檢查;
- 去掉例外支持,Enable C++ Exceptions、Enable Objective-C Exceptions設定為NO,Other C Flags添加-fno-exceptions;
- Strip Debug Symbols During Copy設定為YES,這個是將那些拷貝進專案包的三方庫、資源或者 Extension 的 Debug Symbol 去除掉,這個選項沒有前置條件,只需在Release模式下開啟,否則就不能對三方庫進行斷點除錯和符號化了;
- Build Settings -> Optimization Level有幾個編譯優化選項,release版應該選擇Fastest, Smalllest,這個選項會開啟那些不增加代碼大小的全部優化,并讓可執行檔案盡可能小;
- Enable BitCode設定為YES;
總結
業務的不斷堆積迭代,總會產生一些無用的資源,所以安裝包瘦身要定期清理這些無用檔案和代碼,除了自己寫的代碼外對用到的三方庫也可以做檢查優化,比如有的庫還支持Mac的i386和x86_64架構處理器,這部分代碼就可以根據實際情況洗掉;對比SDK和三方庫的匯入對ipa大小的影響,使用滿足需求的較小庫;專案中重復方法抽離出來等,這些優化可能對安裝包的大小影響很小,但是積少成多,形成對ipa大小敏感的習慣也能幫助我們寫出效率更高的代碼,對安裝包瘦身的探索還有很長的路走,本文也只是列舉了一些常用的瘦身方案,對于龐大的專案,操作起來也是如履薄冰,還好在沒有影響業務和正常功能使用的情況下,我們的ipa減少了大約15MB,優化之路還在繼續,以后還會補充更多的方案,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/41770.html
標籤:其他
