縮減ios可執行文件包的大小是每一個ios開發人員都要經歷的問題,一般首先會對資源文件做處理,壓縮圖片/音頻,去除不必要的資源如@2x和@3x的圖片合并。這些資源優化做完后,我們還可以嘗試對可執行文件進行瘦身,項目越大,可執行文件占用的體積越大,又因為AppStore會對可執行文件加密,導致可執行文件的壓縮率低,壓縮后可執行文件占整個APP安裝包的體積比例大約有80%~90%,還是挺值得優化的,下面說一些壓縮的地方:
1.編譯器的優化---即setting里面一些配置項
Build Settings->Optimization Level有幾個編譯優化選項,release版應該選擇Fastest, Smalllest,這個選項會開啟那些不增加代碼大小的全部優化,并讓可執行文件盡可能小,當然這些編譯項早期是在工程生成時候xcode默認給工程配置好了,如果一旦xcode做了改變我們要知道這些東西。
2.去除符號信息
Strip Linked Product / Deployment Postprocessing / Symbols Hidden by Default在release版本應該設為yes,可以去除不必要的調試符號。Symbols Hidden by Default會把所有符號都定義成”private extern”。這些選項目前都是XCode里release的默認選項,但舊版XCode生成的項目可能不是,可以檢查一下
3.無用代碼
在項目里新建一個類,給它添加幾個方法,但不要在任何地方import它,build完項目后觀察linkmap,你會發現這個類還是被編譯進可執行文件了。
按C++的經驗,沒有被使用到的類和方法編譯器都會優化掉,不會編進最終的可執行文件,但object-c不一樣,因為object-c的動態特性,它可以通過類和方法名反射獲得這個類和方法進行調用,所以就算在代碼里某個類沒被使用到,編譯器也沒法保證這個類不會在運行時通過反射去調用,所以只要是在項目里的文件,無論是否又被使用到都會被編譯進可執行文件。
對此我們可以通過腳本,遍歷整個項目的文件,找出所有沒有被引用的類文件和沒有被調用的方法,在保證沒有其他地方動態調用的情況下把它們去掉。如果整個項目歷時很長,歷時代碼遺留較多,這個清理對可執行文件省出的空間還是挺可觀的。
4.類/方法名長度
觀察linkmap可以發現每個類和方法名都在__cstring段里都存了相應的字符串值,所以類和方法名的長短也是對可執行文件大小是有影響的,原因還是object-c的動態特性,因為需要通過類/方法名反射找到這個類/方法進行調用,object-c對象模型會把類/方法名字符串都保存下來。
對此我們可以考慮在編譯前把所有類和方法名進行混淆,跟壓縮js一樣,把長名字替換成短名字,這樣做的好處除了縮小體積外,還對安全性有很大提升,別人拿到可執行文件對它class-dump出來的結果都是混淆后的類和方法名,就無法從類和方法名中猜出某個方法是做什么的,就難以掛鉤子進行hack。不過這樣做有個缺點,就是crash堆棧反解出來的堆棧方法名會是混淆后的,需要再加一層混淆->原名的轉換,實現和使用成本有點高。實際上這部分占用的長度比較小,中型項目也就幾百K,對安全性要求高的情況可以試試。
5.冗余字符串
代碼上定義的所有靜態字符串都會記錄在在可執行文件的__cstring段,如果項目里Log非常多,這個空間占用也是可觀的,也有幾百K的大小,可以考慮清理所有冗余的字符串。另外如果有特別長的字符串,建議抽離保存成靜態文件,因為AppStore對可執行文件加密導致壓縮率低,特別長的字符串抽離成靜態資源文件后壓縮率會比在可執行文件里高很多.