包大小優化

背景知識

App的大小分為下載大小和安裝大小。
下載大小指的是App壓縮包(.ipa)所占的空間大小。用戶下載的是壓縮包,下載完成后會自動解壓,安裝大小就是指壓縮包解壓后的大小。
下載大小如果超過200MB,iOS13以下無法通過蜂窩網絡下載;iOS13以上會通過用戶手動設置才可以下載。

App Connect上的文件大小

包大小優化

網上有很多包大小優化的方案,我看了很多博客,根據博客總結一下包大小優化相關的操作,如下圖。

包大小優化.png

Xcode編譯設置

  1. 去掉異常支持,Build Setting中Enable C++ Exceptions和Enable Objective-C Exceptions設置為NO,Other C Flags添加-fno-exceptions
去除異常支持.png

注意??:Enable C++ Excptions和Enable Objective-C Exceptions是指項目支持異常處理,關閉后try cache、throw、包括宏定義try{}、@finally{}、@strongify會報錯。
-fno-exceptions的意思是禁用異常機制,參考gcc,同樣,當項目中有try thorw的時候,就不要設置這個選項為NO。

Before detailing the library support for -fno-exceptions, first a passing note on the things lost when this flag is used: it will break exceptions trying to pass through code compiled with -fno-exceptions whether or not that code has any try or catch constructs. If you might have some code that throws, you shouldn't use -fno-exceptions. If you have some code that uses try or catch, you shouldn't use -fno-exceptions.

2.Build Settings -> Architectures,在Excluded Architectures中設置Release模式下 Any iOS SDK -> armv7,設置之后在Release下把armv7排除。

Architetures設置.png

armv6: iPhone, iPhone 3G, iPod 1G/2G
armv7: iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini
armv7s: iPhone 5, iPhone 5c, iPad 4
arm64: iPhone X,iPhone 8(Plus),iPhone 7(Plus),iPhone 6(Plus),iPhone 6s(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)
arm64e: XS/XS Max/XR/ iPhone 11, iPhone 11 pro x86_64: 模擬器64位處理器 i386: 模擬器32位處理器

這里:iOS9之后推出了App Thinning,在這過程中蘋果已經幫忙去掉armv7了。

3.Build Settings -> Generate Debug Symbols設置為NO

調試符號.png

Generate Debug Symbols是生成調試符號,斷點不能用,最后不能生成DSYM文件(DSYM文件是指具有調試信息的目標文件)。建議不要設置為NO。

  1. Build Settings -> Deployment Postprocessing,Debug模式下設置NO,Release下設為YES
    Deployment Postprocessing是Strip配置的總開關
截屏2022-08-11 下午5.12.49.png

Build Settings -> Strip Linked Product,Debug下設置為NO,Release下設置為YES。
設置為Yes時,對最后的二進制文件進行strip,去除不必要的符號信息。
注意??:去除了符號信息之后需要使用dSYM來進行符號化,所以需要將 Debug Information Format 修改為DWARF with dSYM file(Release下),如果在Debug下設置為DWARF with dSYM file那么在崩潰時將無法看到堆棧信息。

Build Settings -> Strip Debug Symbols During Copy,Debug下設置為NO,Release下設置為YES
文件拷貝編譯階段是否進行strip,設置為YES之后,會把拷貝進項目包的三方庫、資源或者Extension的Debug Symbol去除。

5.Build Settings -> Symbols Hidden by Default,Debug模式下設置為NO,Release下設置為YES
Symbols Hidden by Default會把所有符號都定義成"private extern",移除符號信息

symbols.png

6.Build Settings -> Make Strings Read-Only設置為YES
復用字符串字面量

截屏2022-08-11 下午5.16.55.png

7.Build Settings -> Dead Code Stripping設置為YES
消除無效代碼,C/C++/Swift 等靜態語言編譯器會在 link 的時候移除未使用的代碼,對于OC等動態語言是無效的

截屏2022-08-11 下午5.17.30.png
  1. Asset Catalog Compiler編譯設置優化,Build Settings ->
    Compiler - Options 中Optimization改為space
    這個選項可以改變actool在構建Assets.car時選取的編碼壓縮算法,減少包大小
截屏2022-08-11 下午5.18.55.png

9.Build Settins -> Optimization Level改為-Oz

Optimization Level默認為-Os,-Oz是Xcode 11之后才出現的編譯優化選項,核心原理是對重復的連續機器指令外聯成函數進行復用,因此開啟Oz,能減少二進制的大小,但同時會帶來執行效率但額外消耗。

Optimization.png

Optimization Level各參數優化的選擇對比,如下圖,對于性能要求高的,建議選擇-O2和-O3,對于包大小敏感的,可選擇-Os和-Oz,默認-Os是性能和大小平衡比較好的。最終選擇什么,需要讀者根據自己實際項目而定。

參數對比圖.png

Pod設置

在OC的項目中,Podfile如果引用了Swift的第三方庫,一般都會直接打開use_frameworks!,對應的Pod中所有的庫都會
打包成動態庫,以及Swift和OC庫的依賴問題會導致依賴庫增加,會造成包體積增大。所以我們可以有優化為針對單個Swift庫使用use_frameworks!

Podfile修改.png

我按照上述修改后,pod install報錯了,修改方法如下圖。

pod報錯修改方法.png

資源優化

刪除未使用的類

查看了一些文檔后,我使用了python腳本的方法來查找項目中未使用的類。腳本地址如下:
腳本地址
執行方法:
1.cd到腳本所在文件夾中
2.運行下需要檢測的項目后按照如下步驟找到.app文件所在文件夾

app文件位置右鍵顯示.png

3.執行python腳本

python FindClassUnRefs.py -p /Users/a58/Library/Developer/Xcode/DerivedData/XXX-bqqoxganvkvgwuefbskxsbvnxlnn/Build/Products/Debug-iphonesimulator/XXX.app -w JD,BD,AL

參數說明:
-p Xcode運行之后的,項目Product路徑
-w 結果白名單處理,檢測結果,只想要以什么開頭的類,多個用逗號隔開,比如JD,BD,AL
-b 結果黑名單處理,檢測結果,不想要以什么開頭的類,多個用逗號隔開,比如Pod,AF,SD
-w 和 -b 不能共存,共存會報錯

用這個方法并未查找到未使用的category,并且還是需要在項目中進行搜索判斷是否使用該類,結果并不完全準確。

刪除未使用圖片

通過工具LSUnusedResources,運行后,輸入項目文件位置,即可查找未使用的圖片。
LSUnusedResources下載地址

原理大致是遍歷資源目錄下后綴 ["imageset", "jpg", "png"...] 的文件,然后在源文件 ["m", "swift", "xib", "storyboard"...] 中字符串匹配,無匹配則是無用的資源文件。

使用時注意勾選Ignore similar name,然后點擊右上角的Browse選中要掃描的項目地址,點擊右下角的search,就會開始掃描,結果會在底部Unused Results中展示出來,然后CMD+A全選,export,導出到一個文本文件中。也可以在對應單條Item上面雙擊,會打開對應的文件夾。建議刪除前在項目中搜索確認,是否確實沒有使用(類似字符串中間替換的可能會被掃描出來,所以刪除前需要確認)

壓縮圖片

可以通過以下網站壓縮圖片
tinyPNG

tinyPNG網站.png

總結:
以上就是我包大小優化的過程,查看了一些博客,然后根據博客上所說的進行修改。以下是我打包兩個.ipa包的大小對照圖,從32M優化到了19.8M。

ipa文件大小對比.png

Mach-O文件

我們講.ipa文件后綴修改為.zip后解壓,會看到文件中所包含的內容。主要有codeSignature、Assets.car、還有一個exe文件,這個文件的格式是Mach-O。
在這里也可以看到nib文件,因為項目中使用xib文件繪制UI。由此可以知道,如果想要控制包大小,最好不要使用xib文件(個人理解)。

解壓文件.jpg

可以使用MachView來查看Mach-O文件,MachView下載地址如下
MachView下載地址

Mach-O文件主要包括三部分:

  • Header:文件基本屬性、CPU的類型、Load Commands的個數等。
  • Load Commands:由多條Load Command組成,它們描述了Data在二進制文件和虛擬內存中布局,有了這個布局就能夠知道Data的排布情況。
  • Data:存儲的實際內容,主要是程序的指令和數據,按照Load Commands描述排布。
Mach-O文件組成.png
Load Commands內容.png

使用以下指令可以查看Mach-O文件Data部分的結構和大小信息。

xcrun size -lm /Users/boyankeji/Downloads/LianCheng\ 2022-08-09\ 16-43-21/Payload/連成物聯.app/連成物聯 
查看結果.png

如圖所示,主要包括了4部分:

  • __PAGEZERO
  • __TEXT
  • __DATA
  • __LINKEDIT

__PAGEZERO在內存中不可讀不可寫,用于捕獲NULL指針。它并不占用Data的空間。

__TEXT、__DATA保存代碼的指令和數據。

__LINKEDIT包含啟動App需要的信息。

今日頭條優化實踐: iOS 包大小二進制優化,一行代碼減少 60 MB 下載大小這個博客中的包大小優化方法,主要就是將__TEXT段進行遷移。

其中原理是:

When your app is approved for the App Store, it is encrypted with DRM and recompressed. The added encryption and DRM affects the ability to compress your binary, and as a result you may see a larger App Store file size for your binary than the binary you uploaded on App Store Connect. The exact final size for your app cannot be determined in advance to the accuracy of a single byte.

我們將項目進行Archive后生成.xcarchive文件,文件上傳到App Store Connect后,蘋果會對可執行文件進行加密,然后再將App壓縮成.ipa文件,然后發布到App Store。
加密會影響可執行文件的壓縮效率,從而導致ipa大小增加,而這種加密效果幾乎沒用。
Mach-O 文件代碼的解密發生在 Mach-O 文件被加載的時候,由 Mach Loader 進行。Mach Loader 會讀取 Mach-O 中的 LC_ENCRYPTION_INFO 這條 Load Command 來判斷可執行文件是否加密。

判斷ipa文件是否加密.png

cryptid 表示加密方法為 1,如果為 0 表示不加密。

通過以下指令可以查看Load Commands

otool -l /Users/boyankeji/Downloads/LianCheng\ 2022-08-09\ 16-43-21/Payload/連成物聯.app/連成物聯

我們通過查看__TEXT的filesize,通過計算可以知道加密的內容主要在__TEXT上。所以我們將__TEXT移走可以達到減少包大小的目的。

__TEXT.png

注意??:
蘋果在 iOS 13 已經對下載大小做了優化,所以本方案無法再對 iOS 13 的設備的下載大小進一步優化。
即,若用戶的設備 < iOS 13,那么本方案可以減少該設備上 App 32~34%的下載大??;
若用戶的設備 >= iOS 13,本方案不會對該設備的 App 的下載大小有進一步優化,也不會有負面影響。

包大小優化總結

根據查找的博客來看,包大小優化主要是三部分:

  1. Xcode中刪除編譯需要的Symbols、Debug符號等;
  2. 對資源的控制,不要重復引入圖片、過大的資源文件需要進行壓縮;未用的代碼、類需要及時刪除;
  3. 黑科技,根據頭條給出的方案,遷移__TEXT
    以上是我根據最近一段時間的學習總結的,在學習的工程中,會發現自己對程序的構建、腳本的使用、Mach-O文件等都不太了解,現在通過學習感覺也只是皮毛的階段。以后如果有時間需要更加深度的學習。
    通過學習包大小優化的內容,以后在開發的過程中需要增加包大小優化的意識。

學習鏈接

App Store上的包大小
分析iOS包大小優化
iOS 腳本查看項目中未使用的類
iOS檢測項目中無用類和方法
今日頭條優化實踐: iOS 包大小二進制優化,一行代碼減少 60 MB 下載大小
iOS底層探索- Mach-O文件

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • 背景 包大小優化是項目開發中不可避免會遇到的,網上關于包大小優化的文章很多,每篇文章說的都不盡相同,筆者曾經根據網...
    大菠蘿_DABLO閱讀 4,989評論 0 12
  • 背景 移動開發中,對于包大小優化是項目開發中需要考慮的,尤其對于航母級App,比如QQ、手淘等。網上關于包大小優化...
    virusbo閱讀 4,360評論 1 18
  • 官方App Thining App Thining會根據不同的設備提供相應的App包進行下載。 App Thinn...
    擰發條鳥xds閱讀 599評論 0 3
  • 1.官方 App Thinning 官方推出的改善App下載進程的技術 因為現在ios設備屏幕尺寸,分辨率越來越多...
    crazyfox閱讀 517評論 0 5
  • 這里記錄下個人根據相關文檔(基本參照今日頭條分享的文章,鏈接在底部)對開發的某個app進行包大小優化的實踐過程,這...
    QYCD閱讀 1,069評論 0 4