對(duì)iOS安裝包瘦身是很多App都必須要做的事,一般首先會(huì)對(duì)資源文件下手,壓縮圖片/音頻,去除不必要的資源。這些資源優(yōu)化做完后,我們還可以嘗試對(duì)可執(zhí)行文件進(jìn)行瘦身,項(xiàng)目越大,可執(zhí)行文件占用的體積越大,又因?yàn)锳ppStore會(huì)對(duì)可執(zhí)行文件加密,導(dǎo)致可執(zhí)行文件的壓縮率低,壓縮后可執(zhí)行文件占整個(gè)APP安裝包的體積比例大約有80%~90%,優(yōu)化還是有意義的。
分析ipa文件:iOS可執(zhí)行文件的組成
通過(guò)生成LinkMap文件,分析源代碼生成的編譯文件的大小。在Build Settings中Write Link Map File設(shè)置為Yes (記住release時(shí)候不要設(shè)置為Yes)。
編譯之后會(huì)在build目錄中生成兩個(gè)LinkMap文件: XXX-LinkMap-normal-i386和XXX-LinkMap-normal-x86_64,分別代表在模擬器中32位和64位指令集生成的LinkMap文件。
LinkMap的文件詳細(xì)結(jié)構(gòu)解釋
LinkMap會(huì)包含每個(gè)可執(zhí)行文件的偏移量及大小,所以可以很方便的知道每個(gè)可執(zhí)行文件的大小。
編譯目錄文件:~/Library/Developer/Xcode/DerivedData/XXX-eumsvrzbvgfofvbfsoqokmjprvuh/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/
LinkMap分析工具


App瘦身checkList


編譯選項(xiàng)
1.編譯器優(yōu)化級(jí)別
- Optimization Level 使用Fastest, Smalllest
該選項(xiàng)對(duì)安裝包大小影響幾無(wú),但可以提高app的性能。參考wwdc 2013-Session408 Optimize Your Code Using LLVM - Strip Linked Product 設(shè)置為YES
需要注意的是Strip Linked Product也受到Deployment Postprocessing設(shè)置選項(xiàng)的影響。
在Build Settings中,我們可以看到, Strip Linked Product是在Deployment這欄中的,而Deployment Postprocessing相當(dāng)于是Deployment的總開(kāi)關(guān)。記得把Deployment Postprocessing也設(shè)置為YES, 該選項(xiàng)對(duì)安裝包大小的影響非常大。
PS:Deployment Postprocessing這個(gè)配置項(xiàng)如果使用xcode打包,xcode會(huì)默認(rèn)把這個(gè)變量置為YES, 如果使用腳本打包,記得設(shè)置。 - Symbols Hidden by Default設(shè)置為YES
- Make Strings Read-Only 設(shè)置為YES
-
Bitcode設(shè)置為YES( ps:注意項(xiàng)目中的靜態(tài)庫(kù),三方庫(kù)等是否支持,有一個(gè)不支持就用不了,推不動(dòng)別人改~~~)
關(guān)于bitcode, 知道這些就夠了
iOS framework如何支持bitcode以及bitcode檢測(cè)
資源瘦身:
1.清理無(wú)用圖片
2.清理重復(fù)圖片
3.無(wú)損壓縮圖片
代碼瘦身
- 已經(jīng)下線的陳舊代碼,AB試驗(yàn)已經(jīng)下線的代碼
- 通過(guò)轉(zhuǎn)H5、Hybrid或者RN實(shí)現(xiàn)的Native功能,可以定期清理
- 一些非核心Hybrid或者RN模塊,可以考慮不要打包進(jìn)入APP,通過(guò)動(dòng)態(tài)下發(fā)的方式獲取
- 代碼的重構(gòu),UI組件、業(yè)務(wù)邏輯的重用等等
- 冗余字符串
代碼上定義的所有靜態(tài)字符串都會(huì)記錄在在可執(zhí)行文件的__cstring段,如果項(xiàng)目里L(fēng)og非常多,這個(gè)空間占用也是可觀的,也有幾百K的大小,可以考慮清理所有冗余的字符串。另外如果有特別長(zhǎng)的字符串,建議抽離保存成靜態(tài)文件,因?yàn)锳ppStore對(duì)可執(zhí)行文件加密導(dǎo)致壓縮率低,特別長(zhǎng)的字符串抽離成靜態(tài)資源文件后壓縮率會(huì)比在可執(zhí)行文件里高很多。
資源瘦身
1、刪除無(wú)用的圖片文件
LSUnusedResources查找無(wú)用的圖片文件

2、重復(fù)的圖片文件
重復(fù)資源(主要指圖片)不是指命名重復(fù)而是內(nèi)容相同。
Duplicate Photo Finder(App Store有免費(fèi)下載)

fdupes 是Linux下的一個(gè)工具,可以在指定的目錄及子目錄中查找重復(fù)的文件。
fdupes通過(guò)對(duì)比文件的MD5簽名,以及逐字節(jié)比較文件來(lái)識(shí)別重復(fù)內(nèi)容。
項(xiàng)目中圖片目錄,如 Assets.xcassets和images文件夾,所以:
brew install fdupes
fdupes -r xxx/images xxx/Images.xcassets
3、無(wú)損壓縮圖片
ImageOptim進(jìn)行png文件的無(wú)損壓縮
注意:
實(shí)際生產(chǎn)的安裝包體積沒(méi)有變小,因?yàn)?code>COMPRESS_PNG_FILES和STRIP_PNG_TEXT設(shè)置成了YES,Xcode會(huì)重新壓縮一次圖片,但是壓縮之后的圖反而比ImageOptim處理之后的圖更大。改成NO就能讓項(xiàng)目中的PNG保持不變。如果搜不到,手動(dòng)添加一下。



4、WebP圖片壓縮
WebP是Google提供的一種圖片編碼格式,通常情況下WebP格式的圖片是原始JPG/PNG圖片的1/3,所以對(duì)于重度依賴圖片顯示的應(yīng)用,轉(zhuǎn)換使用WebP可以節(jié)省大量的網(wǎng)絡(luò)傳輸數(shù)據(jù)和時(shí)間。對(duì)于APP瘦身,使用WebP格式可能是一種方式,可以使用WebP格式的圖片替代現(xiàn)有的圖片資源,可以一定程度的節(jié)省空間。
注:iOS原生并不支持WebP格式加載,需要引入SDWebImage/WebP
Webp劣勢(shì):(慎用)
- 壓縮時(shí)間長(zhǎng),大概是png的8倍左右(不過(guò)一般都是在服務(wù)端壓縮,客戶端解碼,所以服務(wù)端可以做個(gè)預(yù)壓縮)
- 解碼時(shí)間比png長(zhǎng),大概幾十毫秒。WebP是節(jié)省了流量(圖片小),增加了解碼時(shí)間,換句話說(shuō)就是:同樣的圖片,網(wǎng)絡(luò)越快(圖片更小的WebP就沒(méi)有明顯優(yōu)勢(shì)),圖片越多(WebP要解碼),WebP比png要慢。
- UIWebView,WKWebView都不支持WebP。(UIWebView可以用NSUrlProtocol來(lái)解決,但是WKWebView還沒(méi)有太完美的辦法,誰(shuí)知道的請(qǐng)告訴我下)
- 不支持流式解壓縮(即圖片加載的時(shí)候會(huì)由模糊慢慢變清晰的過(guò)程,WebP貌似不支持這種解壓縮方式)
5、AppThinning
方式一:安裝npm包(需要查看文檔,安裝node環(huán)境)
npm i appthinning -g
方式二:克隆源碼,直接參考文檔
使用:
appthinning -d "/Users/catchzeng/Desktop/test" -t "png|jpg" -s 1000 -m 2000 -c imageOptim

6、AssetCatalogTinkerer
AssetCatalogTinkerer 是一款開(kāi)源的查看和提取 car 文件中的圖片工具。
導(dǎo)出所有圖片后,就可以根據(jù)大小排序找到大文件,進(jìn)行對(duì)應(yīng)的壓縮處理。
代碼瘦身
1、AppCode代碼靜態(tài)檢查
AppCode提供了非常強(qiáng)大的代碼靜態(tài)檢查工具
1.Inspect Code:檢查代碼
2.Code Cleanup:代碼清除
3.Silent Code Cleanup:無(wú)聲代碼清理
4.Run Inspection by Name:自動(dòng)檢查清除冗余資源
5.Configure Current File Analysis:配置當(dāng)前文件分析
6.View Offline Inspection Results:查看離線檢查結(jié)果
7.Infer Nullity:推斷出無(wú)效
8.Locate Duplicates:查找重復(fù)
9.Show Coverage Data:顯示覆蓋數(shù)據(jù)
10.Analyze Dependencies :分析依賴性
11.Analyze Backward Dependencies :分析落后的依賴關(guān)系
12.Analyze Module Dependencies:分析模塊依賴關(guān)系
13.Analyze Dependency Matrix:分析從屬矩陣關(guān)系
14.Analyze Cyclic Dependencies:分析循環(huán)依賴關(guān)系
15.Analyze Data Flow to Here :分析到這里的數(shù)據(jù)流
16.Analyze Data Flow from Here :從這里分析數(shù)據(jù)流
17.Analyze Stack Trace :分析堆棧追蹤
自動(dòng)檢查清除冗余資源詳細(xì)功能Name對(duì)應(yīng)Idea中Preferences—>Editors—>Inspections中所有內(nèi)容
1、清理無(wú)效類(lèi) Run Inspection by Name:Empty Class
2、查看未使用方法 Run Inspection by Name:Unused declaration
包含了項(xiàng)目里面聲明了沒(méi)用使用過(guò)的變量,方法和類(lèi)
對(duì)于檢測(cè)的內(nèi)容,idea提供四種解決方案
3、查看類(lèi)中有未使用引用 Run Inspection by Name:Unused import
可以參考AppCode inspections for your code perfection
2、清除無(wú)用代碼
01. AppCode搜索出來(lái)的無(wú)用的Class,會(huì)有誤報(bào)需要仔細(xì)檢查每一個(gè)報(bào)錯(cuò)的代碼。
02. 使用Fui查找發(fā)現(xiàn)無(wú)用文件,可以用于查找無(wú)用的import,同時(shí)也提供xcfui 可以和Xcode集成。
清除無(wú)用類(lèi)
fui find
fui --path=~/source/project/Name --ignore-path=Pods --ignore-path=Libraries find
- 清除無(wú)用的Import
fui -g --path=~/source/project/Name --ignore-path=Pods find
fui -l --path=~/source/project/Name --ignore-path=Pods find
03. SMCheckProject使用
由于clang插件檢索出的無(wú)用方法沒(méi)法確定能夠直接刪除,還需要挨個(gè)檢索人工判斷是否可以刪除,這樣每次要清理是需要人工排查一遍是非常耗時(shí)耗力的。這里推薦一個(gè)使用Swift3寫(xiě)的MacOS程序,這個(gè)工具可以很方便快捷的找出工程項(xiàng)目下未被調(diào)用的方法可以檢測(cè)出objc項(xiàng)目中無(wú)用的方法,支持一鍵清理。

注意點(diǎn):
01:編譯工程:作者的swift版本是3.0 2020.12.12 swift需要支持5.0
01.png
02.png
02:項(xiàng)目中路徑fix
03:語(yǔ)法錯(cuò)誤,根據(jù)提示fix一下
04: 工程路徑需要寫(xiě)對(duì),不然找不到具體的類(lèi)。
05: 一鍵清理的時(shí)候語(yǔ)法報(bào)錯(cuò):改成 URL(fileURLWithPath:mFilePath)
06:清理的方法有可能是子類(lèi)繼承,category,base類(lèi),potocol,有的拼接的方法。需要自己再仔細(xì)確認(rèn)一下。
(瘦身收益不大,還容易出問(wèn)題,謹(jǐn)慎刪除)
04 . 查找相似的代碼:SameCodeFinder可以查找到相似的代碼,最后一位數(shù)字代表兩個(gè)文件的海明距離,數(shù)字越小說(shuō)明兩個(gè)文件越類(lèi)似。
清除無(wú)用的Method
xib/stroyboard替換
無(wú)用三方庫(kù)刪除
-
靜態(tài)庫(kù)瘦身
暫時(shí)還沒(méi)選擇,可以參考文章iOS APP安裝包瘦身實(shí)踐
項(xiàng)目中多少都會(huì)引入一些第三方靜態(tài)庫(kù),通過(guò)lipo工具可以查看支持的指令集,比如:
lipo -info libWeChatSDK.a
i386,x86_64,這不是模擬器的指令集么?去掉看能不能減少體積?armv7可以兼容armv7s,armv7s也可以刪了,只保留armv7和arm64lipo libWeChatSDK.a -thin armv7 -output libWeChatSDK-armv7.a lipo libWeChatSDK.a -thin arm64 -output libWeChatSDK-arm64.a lipo create libWeChatSDK-armv7.a libWeChatSDK-arm64.a -output libWeChatSDK-device.a ls -ll -rw-r--r-- 1 Vic staff 5957080 Jan 6 14:40 libWeChatSDK-device.a -rw-r--r-- 1 Vic staff 14410376 Nov 25 11:53 libWeChatSDK.a



ipa優(yōu)化了5M左右。大部分是圖片資源,和無(wú)用的文件。
參考文章
iOS可執(zhí)行文件瘦身
iOS APP瘦身實(shí)踐,資源優(yōu)化、編譯器配置優(yōu)化、可執(zhí)行文件優(yōu)化
滴滴出行iOS端瘦身實(shí)踐, 提供了查找無(wú)用圖片的工具、WebP圖片壓縮、基于clang plugin實(shí)現(xiàn)查找無(wú)用代碼、查找類(lèi)似代碼
基于clang插件的一種iOS包大小瘦身方案
檢測(cè)出objc項(xiàng)目中無(wú)用方法,然后一鍵全部清理
lipo command(Mac)
iOS APP分析無(wú)用代碼
iOS 安裝包瘦身 (上篇)
iOS 安裝包瘦身(下篇)
AppCode使用技巧(一)——Inspections
AppCode使用技巧(二)——Completion
AppCode使用技巧(三)——實(shí)時(shí)模板
AppCode使用技巧(四)——搜索和導(dǎo)航
優(yōu)化安裝包大小
iOS APP應(yīng)用包瘦身綜合實(shí)踐小結(jié)
工具篇——idea的清理無(wú)效代碼
今日頭條優(yōu)化實(shí)踐: iOS 包大小二進(jìn)制優(yōu)化,一行代碼減少 60 MB 下載大小

