隨著項(xiàng)目開發(fā)的不斷迭代,工程越來越大,ipa安裝包也越來越大,這非常不利于App的推廣工作。

我們的項(xiàng)目比較老,大概有6年的歷史了,團(tuán)隊(duì)維護(hù)人員的不斷更替,給項(xiàng)目留下了很多詬病,ipa過大就是其中之一,曾經(jīng)達(dá)到了110多M。由于我們的App由三個(gè)團(tuán)隊(duì)共同開發(fā),我們?yōu)榱薃pp的瘦身工作也忙活了好一陣子,非常不容易。
編譯選項(xiàng)優(yōu)化
- BuildSettings->Optimization Level,Xcode默認(rèn)設(shè)置為“Fastest ,Smallest”,保持默認(rèn)即可。
- Build Settings-> Linking->Dead Code Stripping 設(shè)置成 YES
- Deployment Postprocessing 設(shè)置成YES
- Strip Linked Product 設(shè)置成YES
- 工程的Enable C++ Exceptions和Enable Objective-C Exceptions選項(xiàng)都設(shè)置為NO。手動(dòng)管理異常。
- symbols hidden by default選項(xiàng)設(shè)置為YES。
- 所有沒有使用C++動(dòng)態(tài)特性的lib庫(搜索工程沒有使用dynamic_cast關(guān)鍵字) Enable C++ Runtime Types 選項(xiàng)設(shè)置為NO。
資源文件的瘦身工作
我們都知道,ipa是由 資源文件 和 可執(zhí)行文件 構(gòu)成。資源文件包括 圖片 、 音頻 、 視頻 、 字體 、 plist 、 text 、 md 、 cmake 、 License 等等的非代碼文件。
圖片資源壓縮
首先,我們要排除那些我們不需要的資源文件,最簡單的方式就是全局去搜這個(gè)資源的文件名稱。由于資源文件是ipa size中占比較大的,所以我們應(yīng)當(dāng)考慮這個(gè)資源(比如字體,視頻等)是否真的有必要加入到工程中。(或者可以考慮網(wǎng)絡(luò)下載的方式?)
工程中最多的資源文件可能就是圖片了,我們可以把打好的ipa包解開,按文件大小排個(gè)序,看看哪些資源文件是占用較大的,如果工程歷史比較久遠(yuǎn),那么一定存在著很多沒有使用的圖片卻引在了工程中,如何把這些圖片篩選出來,是個(gè)問題。
可以使用腳本來查,但是缺點(diǎn)也很明顯,慢,不準(zhǔn)確。也可以使用LSUnusedResources.app來查找,他的速度很快,但是缺點(diǎn)也很明顯。比如我們有一組圖片,所以我們使用圖片名稱字符串的時(shí)候采用的是圖片名稱的拼接,這種情況LSUnusedResources.app是檢測(cè)不到的。對(duì)于檢索出來的結(jié)果,還需要我們仔細(xì)甄別。
下載: LSUnusedResources.app.zip
其次,我們要做的就是必要資源的壓縮工作了。一般情況下我們都會(huì)使用PNG格式的圖片,相比于JPG來說,它支持完整的透明通道。一般會(huì)提供@2x和@3x的圖片,如果對(duì)視覺要求不是特別高的話,可以只提供@2x的圖片,但是在5.5-inch的屏幕上會(huì)放大1.5倍。我們一般是在 tinypng.com 壓縮PNG圖片,壓縮效率還是挺高的,通常會(huì)降低一個(gè)數(shù)量級(jí),但是每次只能壓縮20張圖片。不過也可以使用 TinyPNG Mac客戶端 來壓縮圖片,需要注冊(cè)一個(gè)API Key。
使用Icon Font
每個(gè)iconfont只是一小段文本,size要比圖片形式的icon小一個(gè)數(shù)量級(jí),我們可以像使用字體一樣來使用圖片。
生成iconfont需要 矢量圖 。一些網(wǎng)站提供生成iconfont的服務(wù),比如icomoon和Fontello。阿里巴巴矢量圖標(biāo)庫和easyicon提供大量優(yōu)秀的矢量圖。
icomoon和Fontello均可以通過導(dǎo)入SVG圖標(biāo)或者選擇網(wǎng)站自身提供的圖標(biāo)來生成iconfont。值得一提的是,icomoon還可以生成PNG,PDF,CSH等格式。
在生成的文件夾中,可以找到擴(kuò)展名為 .ttf 的字體集文件。
FontAwesomeKit
using-icon-font-in-ios
使用WebP
WebP是Google推的方案,無損壓縮后的WebP比PNG少了45%的size,即使PNG經(jīng)過其他工具壓縮之后,WebP還是可以減少28%的size。SDWebImage實(shí)現(xiàn)了加載WebP格式圖片的功能,但是沒有做緩存功能,可能需要我們自己來實(shí)現(xiàn)了。
使用PDF矢量圖
Xcode6以后支持了矢量圖,但是PDF矢量圖貌似并不能達(dá)到瘦身的目的,使用矢量圖編譯打包后在ipa內(nèi)是一個(gè)car文件,可以用工具解壓出里面的恩圖片,會(huì)發(fā)現(xiàn)PDF轉(zhuǎn)成了 @1x、@2x、@3x 3套圖片。不過iOS9以后蘋果提供了App Thinning 方案(App Slicing、on-demand resources、Bitcode)。
圖片資源優(yōu)化
- 不透明的大圖片壓縮成JPG格式
- 大背景圖如果一定要是PNG格式,可以把它保存為WebP格式,不過要注意有沒有太大失真情況
- 如果可以,盡量使用網(wǎng)絡(luò)加載圖片
- 類似皮膚功能,使用網(wǎng)絡(luò)下載皮膚包
- 避免使用大量圖片的組合幀動(dòng)畫
- 如果圖片不是很復(fù)雜,使用代碼繪制
- 加入到
Assets.xcassets中,只支持PNG格式的圖片,圖片只支持[UIImage imageNamed]的方式實(shí)例化,但是不能從Bundle中加載
可執(zhí)行文件的瘦身
首先我們通過LinkMap來查看編譯后,我們各個(gè)類庫的空間占用情況。我們先在Build setting中把LinkMap的開關(guān)打開

正如上圖所示,只需要把Write Link Map File設(shè)置為YES,就可以了。其存儲(chǔ)目錄為/Users/用戶名/Library/Developer/Xcode/DerivedData/項(xiàng)目名稱/Build/Intermediates/項(xiàng)目名稱.build/Debug-iphonesimulator/項(xiàng)目名稱.build/項(xiàng)目名稱-LinkMap-normal-x86_64.txt
然后可以使用一個(gè)js腳本來把LinkMap中的內(nèi)容做個(gè)排序:
node linkmap.js filepath -hl
filepath即LinkMap.txt的path
根據(jù)這個(gè)排序列表,我們可以有針對(duì)性的去優(yōu)化占用較大的類庫,如果不是必要的類或者第三方庫,要么尋找輕量級(jí)替代方案,要么就刪了吧。
查找工程中未使用的類
這里有一個(gè)腳本工具
python py文件目錄 Xcode工程文件根目錄
會(huì)將結(jié)果以.txt的方式存儲(chǔ)在Xcode工程文件目錄中,但是需要注意的是,由于.a以及FrameWork的存在,還有注釋等客觀因素存在,掃描出來的結(jié)果僅供參考,還需要仔細(xì)甄別。
精益求精
- 刪除代碼中的無用的函數(shù),空函數(shù),默認(rèn)方法,重復(fù)代碼
- 如果不需要系統(tǒng)生成getter和setter方法,盡量不使用@property
- 使用C函數(shù)進(jìn)行一些類封裝
- 插件化:Lua、JSPatch等等
- 使用MRC
- 減少類名方法名長度
- 刪除冗余字符串
查看ipa在Appstore中的大小
我們做了一圈優(yōu)化之后,打出的ipa包也比之前小了不少,但是我們?cè)趺纯吹皆贏ppstore中實(shí)際減少到了多少呢?
我們可以先把ipa包提交到Appstore,并不需要提交審核
- 登錄
iTunes Connect - 選擇
我的App - 進(jìn)入
活動(dòng) - 選擇
所有構(gòu)建版本 - 選擇剛剛上傳的構(gòu)建版本
- 點(diǎn)擊
App Store 文件大小
這樣就看到了我們App在各個(gè)機(jī)型上的空間占用情況,這個(gè)還是非常準(zhǔn)確的。
總結(jié)
安裝包瘦身的工作到此也告一段落了,由于我們是多個(gè)團(tuán)隊(duì)共同開發(fā),所以瘦身工作并不是我們一方的事情,需要多方面共同努力,包括產(chǎn)品,設(shè)計(jì)師等。減肥之后,更重要的是維持一個(gè)良好的身材,為此我們也定了一些規(guī)則,與設(shè)計(jì)師之間的出圖規(guī)則,與產(chǎn)品之間的一些功能調(diào)整的規(guī)則,以及規(guī)定兄弟團(tuán)隊(duì)給我們提供.a或者FrameWork的大小限制等等。同時(shí)我們本身也要提高代碼的整潔程度,這樣關(guān)于安裝包的大小控制,就有了一個(gè)良性的發(fā)展。