iOS安裝包大小優(yōu)化

背景

移動(dòng)開發(fā)中,對于包大小優(yōu)化是項(xiàng)目開發(fā)中需要考慮的蔬螟,尤其對于航母級App此迅,比如QQ、手淘等旧巾。網(wǎng)上關(guān)于包大小優(yōu)化的文章很多耸序,每篇文章說的都不盡相同,因此想根據(jù)已有的文章鲁猩、知識結(jié)合自己的理解坎怪、實(shí)踐,做一份梳理廓握。整理自己的包大小優(yōu)化邏輯搅窿,不光要知道怎么做可以讓包大小變化,還要知道為什么這么做能產(chǎn)生效果隙券。

分析

想要優(yōu)化安裝包大小男应,首先需要弄清楚影響安裝包大小的因素有哪些?在做這件事之前要先思考娱仔、分析沐飘、最后再去做,針對安裝包大小拟枚,首先分析影響安裝包大小的因素薪铜,有:Xcode的設(shè)置、資源恩溅、代碼三個(gè)方面隔箍。那針對這三個(gè)方面要如何優(yōu)化?又如何查看每一步優(yōu)化的結(jié)果脚乡?

首先是怎么優(yōu)化的問題:

Xcode的編譯設(shè)置優(yōu)化蜒滩,Xcode設(shè)置影響的是生成包的大小滨达,通過Xcode編譯選項(xiàng)優(yōu)化的設(shè)置,讓生成的ipa包變小俯艰,比如不含斷點(diǎn)調(diào)試捡遍、去掉異常支持等等。

資源文件的優(yōu)化竹握,資源不光有圖片資源画株,也包含代碼資源和其它導(dǎo)入的資源,可以通過分析安裝包構(gòu)成啦辐,看里面哪些部分比較大谓传、不合理,從而進(jìn)行優(yōu)化芹关。

代碼的優(yōu)化续挟,通過Link Map生成Link Map File,在編譯時(shí)開啟Xcode Build Settings中的Write Link Map File開關(guān)侥衬,Xcode就會(huì)生成一份Link Map File, 分析Link Map File各文件占用诗祸,結(jié)合iOS 上的可執(zhí)行文件 (Mach-O文件)進(jìn)行分析優(yōu)化。

link_map

Link Map File 分為三部分:Object Files轴总、Sections 和 Symbols直颅。

· Object Files 包含了代碼工程的所有文件;

· Sections 描述了代碼段在生成的Mach-O里的偏移位置和大兄庀啊际乘;

· Symbols 會(huì)列出每個(gè)方法、類漂佩、block,以及它們的大小罪塔。

link_map_file

然后是怎么查看每一步優(yōu)化的結(jié)果的問題:

查看每一步的優(yōu)化結(jié)果投蝉,可以通過分析打包出來的ipa的大小以及ipa的組成與初始的ipa包大小比較,即可直觀得到優(yōu)化的結(jié)果征堪。但可以更進(jìn)一步分析ipa的構(gòu)成瘩缆,對比優(yōu)化后的構(gòu)成,看每一步的操作具體影響的是包的哪一塊兒佃蚜,從而導(dǎo)致包的大小發(fā)生了變化庸娱。所以先來看一下一個(gè)ipa包含哪些內(nèi)容,然后每一步優(yōu)化之后谐算,對應(yīng)ipa的哪一部分發(fā)生了變化熟尉。

安裝包的構(gòu)成

iOS打包出來的ipa本質(zhì)上是一個(gè)壓縮包,所以可以將.ipa的后綴改為.zip洲脂,然后進(jìn)行解壓縮斤儿,之后會(huì)得到一個(gè)Payload文件夾,里面又一個(gè)xxx.app的文件,這個(gè)xxx.app就是包含所有文件的包了往果,選中xxx.app疆液,右鍵顯示包內(nèi)容,我們就可以直觀地看到安裝包中的內(nèi)容了陕贮,大致如下:

安裝包結(jié)構(gòu)
安裝包結(jié)構(gòu)解釋

了解了ipa包的組成之后堕油,我們再回過頭來,按照Xcode的編譯優(yōu)化肮之、資源文件優(yōu)化掉缺、代碼優(yōu)化的步驟來一步步分析。

Xcode編譯設(shè)置

一般這一步容易被人忽略局骤,因?yàn)樘岬絻?yōu)化最先能想到的就是資源優(yōu)化攀圈,比如圖片壓縮、無用代碼刪除等等峦甩,而對于Xcode自身的編譯優(yōu)化提及的反而不多赘来。而且由于網(wǎng)上提供的參考針對每個(gè)項(xiàng)目可能結(jié)果都不一樣,有些編譯選項(xiàng)的設(shè)置是需要針與實(shí)際項(xiàng)目結(jié)合起來才可以凯傲,所以這里整理如下:

Xcode編譯優(yōu)化相關(guān):

1.Build Settings中去掉異常支持犬辰,Enable C++ Exceptions和Enable Objective-C Exceptions設(shè)置為NO,Other C Flags添加-fno-exceptions冰单;

excptions

注意:Enable C++ Excptions和Enable Objective-C Exceptions是指項(xiàng)目支持對錯(cuò)誤的異常處理幌缝,比如try catch、throw之類的诫欠;所以如果項(xiàng)目中使用的有類似的異常處理的涵卵,這個(gè)關(guān)閉了之后會(huì)報(bào)錯(cuò)(Cannot use '@try' with Objective-C exceptions disabled)。包括宏定義中使用的有try{}荒叼、@finally{}之類的轿偎,比如@strongify等,如果關(guān)閉了最后打包的時(shí)候也會(huì)報(bào)錯(cuò)被廓。

-fno-exceptions的意思是禁用異常機(jī)制坏晦,參考GCC如下圖,同樣當(dāng)項(xiàng)目中有try throw的時(shí)候嫁乘,就不要設(shè)置這個(gè)選項(xiàng)為NO

fno-exceptions

2.Build Settings -> Architectures昆婿,Release下設(shè)置為arm64

arm64

Architectures指定工程被編譯成可支持哪些指令集類型,支持的指令集越多蜓斧,就會(huì)編譯出多個(gè)指令集代碼的數(shù)據(jù)包仓蛆,ipa包就會(huì)變大。默認(rèn)的參數(shù)standard architectures(armv7,arm64) 法精,打的包里面有32位多律、64位兩份指令集痴突。如果不需要32位的,可以在other中更改支持的指令集狼荞,從而使ipa包變小辽装。

還有另外一種設(shè)置方法,Architectures不修改相味,Excluded Architectures中設(shè)置Release模式下?Any iOS SDK?-> armv7拾积,也可以實(shí)現(xiàn)同樣的效果。設(shè)置了之后丰涉,就是Release下把a(bǔ)rmv7的指令集排除在外拓巧。選中target會(huì)發(fā)現(xiàn)默認(rèn)設(shè)置了?Any iOS Simulator SDK?-> arm64,意思是模擬器的時(shí)候排除arm64指令集一死。

armv7

3.Build Settings -> Generate Debug Symbols設(shè)置為NO

debug_symbols

Generate Debug Symbols的意思是生成調(diào)試符號肛度,當(dāng)這個(gè)選項(xiàng)設(shè)置為YES時(shí),每個(gè)源文件在編譯成.o文件時(shí)投慈,編譯參數(shù)多了-g和-gmodule承耿,意思是generate complete debug info,所以產(chǎn)生的.o文件會(huì)大伪煤,從而最終生成的可執(zhí)行文件也就會(huì)變大加袋。

注意Generate Debug Symbols設(shè)置為NO時(shí),在Xcode中設(shè)置的斷點(diǎn)不會(huì)中斷抱既,即不能斷點(diǎn)調(diào)試职烧。且最后不能生成dSYM文件,即使Debug Information Format設(shè)置了防泵,也不能生成蚀之,因?yàn)槭紫纫姓{(diào)試信息然后才能生成dSYM文件,而設(shè)置為NO捷泞,意味著不產(chǎn)生調(diào)試信息恬总,所以也就沒辦法生成dSYM文件。所以建議不要設(shè)置肚邢。

4.Build Settings -> Deployment Postprocessing,Debug模式下設(shè)置NO拭卿,Release下設(shè)為YES

postprocessing

Deployment Postprocessing是Strip配置的總開關(guān)骡湖,只有這個(gè)設(shè)置為YES之后,下面的Strip Linked Product峻厚、Strip Debug Symbols During Copy的設(shè)置才會(huì)生效响蕴。

a.Build Settings -> Strip Linked Product,Debug下設(shè)置為NO惠桃,Release下設(shè)置為YES

對最后生成的二進(jìn)制文件進(jìn)行strip浦夷,去除不必要的符號信息辖试,Release下可以為YES。注意劈狐,如果Deployment Postprocessing不打開罐孝,該選項(xiàng)沒有作用。去除了符號信息之后需要使用dSYM來進(jìn)行符號化肥缔,所以需要將 Debug Information Format 修改為DWARF with dSYM file(Release下)莲兢,如果在Debug下設(shè)置為DWARF with dSYM file那么在崩潰時(shí)將無法看到堆棧信息。

b.Build Settings -> Strip Debug Symbols During Copy续膳,Debug下設(shè)置為NO改艇,Release下設(shè)置為YES

文件拷貝編譯階段是否進(jìn)行strip,設(shè)置為YES之后坟岔,會(huì)把拷貝進(jìn)項(xiàng)目包的三方庫谒兄、資源或者Extension的Debug Symbol去除。同樣社付,如果Deployment Postprocessing不打開承疲,該選項(xiàng)沒有作用

c.Build Settings -> Symbols Hidden by Default,Debug模式下設(shè)置為NO瘦穆,Release下設(shè)置為YES

symbols_hidden

Symbols Hidden by Default會(huì)把所有符號都定義成"private extern"纪隙,移除符號信息。

5.Build Settings -> Make Strings Read-Only設(shè)置為YES

reuse_string

官方解釋:Make Strings Read-Only (GCC_REUSE_STRINGS), Reuse string literals. 就是復(fù)用字符串字面量扛或,提到復(fù)用绵咱,顧名思義就是減少生成不必要的,也是優(yōu)化的一種形式熙兔。

6.Build Settings -> Dead Code Stripping設(shè)置為YES

dead_code

消除無效代碼悲伶,C/C++/Swift 等靜態(tài)語言編譯器會(huì)在 link 的時(shí)候移除未使用的代碼,對于OC等動(dòng)態(tài)語言是無效的住涉。

7.Asset Catalog Compiler編譯設(shè)置優(yōu)化麸锉,Build Settings -> Asset Catalog Compiler - Options 中Optimization改為space。

optimization

這個(gè)選項(xiàng)可以改變actool(compile asset catalog這個(gè)過程使用的工具舆声,內(nèi)置在Xcode里的)在構(gòu)建Assets.car時(shí)會(huì)按照一定策略選取編碼算法花沉,對其中的 png 圖片重新編碼, 從而減少包大小媳握。Assets.xcassets 壓縮格式對最終ipa包下assets.car文件大小的影響還是比較大的碱屁。但需要注意的是,cocoapods管理庫中的asset catalog的編譯過程在cocoapods生成的[CP] Copy Pods Resources這個(gè)腳本中蛾找,故上面的設(shè)置對Pod庫組件是無效的娩脾。壓縮策略有如下幾種:

asset_catalog

8.Build Settings -> Optimization Level改為-Oz

optimization_level

Optimization Level默認(rèn)為-Os,-Oz是Xcode 11之后才出現(xiàn)的編譯優(yōu)化選項(xiàng)打毛,核心原理是對重復(fù)的連續(xù)機(jī)器指令外聯(lián)成函數(shù)進(jìn)行復(fù)用柿赊,因此開啟Oz俩功,能減少二進(jìn)制的大小,但同時(shí)會(huì)帶來執(zhí)行效率但額外消耗碰声」铗眩可參考What's New in Clang and LLVM

在What's New in Clang and LLVM的Presentation Slides中,蘋果給出了Optimization Level各參數(shù)優(yōu)化的選擇對比奥邮,如下圖万牺,對于性能要求高的拾枣,建議選擇-O2和-O3该互,對于包大小敏感的婚瓜,可選擇-Os和-Oz票唆,默認(rèn)-Os是性能和大小平衡比較好的希太。最終選擇什么侥祭,需要開發(fā)者根據(jù)自己實(shí)際項(xiàng)目而定平痰。

optimization_level_cood

Optimization Level各參數(shù)對比:

optimization_level_contrast

Xcode編譯設(shè)置優(yōu)化總結(jié)如下:

xcode_optimization_summary

資源文件優(yōu)化

資源文件的優(yōu)化款违,通常來說是比較簡單的藕坯,但是資源文件的優(yōu)化是需要持續(xù)進(jìn)行的团南,前面介紹的Xcode編譯設(shè)置優(yōu)化,配置好了之后炼彪,后續(xù)開發(fā)過程中只要不修改配置吐根,都無需重復(fù)關(guān)注。但資源文件不同辐马,隨著項(xiàng)目的迭代拷橘,會(huì)不斷引入新的資源文件,不斷有廢棄資源的產(chǎn)生喜爷,所以資源文件的優(yōu)化是要持續(xù)進(jìn)行的冗疮。

資源文件的優(yōu)化分為兩部分,即:無用資源的刪除檩帐、已用資源的壓縮术幔。在這里建議分先后順序,即先做刪除再做壓縮湃密,因?yàn)槿绻葔嚎s了诅挑,結(jié)果發(fā)現(xiàn)是無用資源,就白白浪費(fèi)了力氣泛源。

無用資源的刪除:

· 已定義未使用的代碼文件

· 已廢棄業(yè)務(wù)揍障,代碼還在

· 已引用的圖片但未使用

· 某些重復(fù)資源導(dǎo)入

已用資源的壓縮:

·項(xiàng)目中引入圖片、網(wǎng)頁俩由、json、音頻等文件的壓縮

無用資源的刪除

隨著項(xiàng)目的迭代癌蚁,每個(gè)項(xiàng)目都會(huì)或多或少存在冗余幻梯《祷可能是開發(fā)了的功能未上線但產(chǎn)品讓保留,保留著保留著就忘記了碘梢;可能是已下線的業(yè)務(wù)咬摇,沒人通知到開發(fā),于是代碼邏輯一直都在煞躬;可能是刪除某些業(yè)務(wù)代碼時(shí)肛鹏,對應(yīng)的圖片資源未刪除;又或者是每個(gè)開發(fā)恩沛,導(dǎo)入各自熟悉的第三方庫使用在扰。

已定義未使用的代碼

可使用AppCode進(jìn)行分析,打開AppCode雷客,待索引完成后芒珠,選擇頂部菜單中的Code->Inspect Code,然后選擇范圍搅裙,whole Project點(diǎn)擊OK皱卓,等待AppCode靜態(tài)分析即可。靜態(tài)分析完以后部逮,可以在Unused code里看到所有的無用代碼

appcode1


appcode2

AppCode中無用代碼靜態(tài)分析的類型有以下幾種:

appcode_types

AppCode靜態(tài)分析結(jié)果出來之后娜汁,刪除前要經(jīng)過確認(rèn),因?yàn)殪o態(tài)分析的結(jié)果可能會(huì)有誤差兄朋,比如針對performSelector調(diào)用的方法就會(huì)被檢測為沒有調(diào)用掐禁。

當(dāng)然也可以不利用AppCode,比如通過技術(shù)手段分析Mach-O文件 :

Mach-O文件中有__DATA.__objc_classrefs和__DATA.__objc_selrefs段蜈漓,分別近似于“被使用的類的集合”和“被使用的方法的集合”穆桂。通過取差集的方式可以篩選出未被使用的類和方法。

1. 排查無用類

使用otool命令可查看__DATA.__objc_classrefs段和__DATA.__objc_classlist段融虽,兩者的差集可以認(rèn)為是定義了但未使用的類享完。

不過__DATA.__objc_classrefs段和__DATA.__objc_classlist段中都只提供了類在二進(jìn)制文件中的位置地址,而沒有提供類名等可讀信息有额。所以在獲取到差集后般又,還需要結(jié)合下面這個(gè)命令的輸出,將地址轉(zhuǎn)換成可讀的類名巍佑。

使用腳本篩選出差集對應(yīng)的類后茴迁,還需要進(jìn)行一遍人工梳理,因?yàn)閯?dòng)態(tài)使用的類萤衰、從nib或storyboard初始化的類以及在同一個(gè)文件中定義的多個(gè)類會(huì)被誤判為未使用的類堕义。

2.?排查無用方法

所有已經(jīng)被實(shí)現(xiàn)的方法可以通過linkmap來獲取,對linkmap做grep操作即可獲得結(jié)果:

而所有已經(jīng)被使用的方法可以通過對二進(jìn)制文件逆向獲得脆栋。使用otool工具逆向二進(jìn)制文件的__DATA.__objc_selrefs?段倦卖,提取可執(zhí)行文件里引用到的方法名:

使用這種方法取到的差集洒擦,還需要排除掉系統(tǒng)API中的protocol,accessor方法等怕膛。

已廢棄業(yè)務(wù)熟嫩,代碼還在

需要梳理業(yè)務(wù)流程,結(jié)合線上業(yè)務(wù)數(shù)據(jù)點(diǎn)擊量褐捻,同產(chǎn)品和業(yè)務(wù)確認(rèn)對應(yīng)功能是否下線掸茅,從而決定是否移除對應(yīng)的業(yè)務(wù)模塊代碼。

已引入未使用圖片

推薦使用工具LSUnusedResources柠逞,原理大致是遍歷資源目錄下后綴 ["imageset", "jpg", "png"...] 的文件昧狮,然后在源文件 ["m", "swift", "xib", "storyboard"...] 中字符串匹配,無匹配則是無用的資源文件边苹。

使用時(shí)注意勾選Ignore similar name陵且,然后點(diǎn)擊右上角的Browse選中要掃描的項(xiàng)目地址,點(diǎn)擊右下角的search个束,就會(huì)開始掃描慕购,結(jié)果會(huì)在底部Unused Results中展示出來,然后CMD+A全選茬底,export沪悲,導(dǎo)出到一個(gè)文本文件中。也可以在對應(yīng)單條Item上面雙擊阱表,會(huì)打開對應(yīng)的文件夾殿如。建議刪除前在項(xiàng)目中搜索確認(rèn),是否確實(shí)沒有使用(類似字符串中間替換的可能會(huì)被掃描出來最爬,所以刪除前需要確認(rèn))

LSUnusedResources

某些重復(fù)資源的導(dǎo)入

重復(fù)資源的導(dǎo)入涉馁,分為兩個(gè)方面,一方面是針對第三方SDK爱致,另一方面是項(xiàng)目文件烤送。

1.針對第三方SDK

項(xiàng)目中功能類似的SDK建議保留一個(gè),建議分析相同功能的類庫糠悯,結(jié)合實(shí)際情況帮坚,保留一個(gè)即可;另外互艾,有些第三方類庫導(dǎo)入時(shí)试和,可只導(dǎo)入實(shí)際使用的部分,不需全量導(dǎo)入纫普,比如百度地圖阅悍,定位和地圖分開的,開發(fā)者根據(jù)需求來選擇需要導(dǎo)入哪些。

2.針對項(xiàng)目文件

使用 fdupes 工具進(jìn)行重復(fù)文件掃描溉箕,原理是:通過校驗(yàn)所有資源的 MD5晦墙,篩選出項(xiàng)目中的重復(fù)資源。這里還要說下cocoapods帶來的圖片重復(fù)合并問題肴茄,也屬于這個(gè)范疇。現(xiàn)如今好多大的App都實(shí)行組件化但指,重度使用cocoapods進(jìn)行庫管理寡痰,越來越多的代碼被封裝成了pod庫,以庫的形式集成進(jìn)工程中棋凳。在檢查安裝包內(nèi)容時(shí)拦坠,看下.app文件的最外層的零散資源文件和pod庫的asset catalog里的資源文件重復(fù)了。因?yàn)槿绻鹥od庫在編寫podspec的時(shí)候剩岳,可能用了這樣的語句指定資源文件:

podspec中這樣書寫贞滨,會(huì)導(dǎo)致asset catalog中的圖片,既作為asset catalog被合并到主工程的asset.car中拍棕,也會(huì)作為png被拷貝到安裝包中晓铆。導(dǎo)致其中一套圖片白白占用了安裝包空間。應(yīng)該以白名單的形式明確指定哪些資源文件是pod庫中有效的資源文件绰播。

已用資源的壓縮

項(xiàng)目中引入圖片骄噪、網(wǎng)頁、json蠢箩、音頻等文件的壓縮链蕊,網(wǎng)頁的壓縮指的是,放入App資源中的js文件谬泌,最好是經(jīng)過H5端壓縮后的滔韵。json文件的壓縮,如果不是打開App時(shí)馬上要用到的數(shù)據(jù)掌实,可采取把對應(yīng)資源放到服務(wù)端陪蜻,下載后使用。音頻文件的壓縮潮峦,則是在可接受的范圍之內(nèi)囱皿,選擇系統(tǒng)可支持的壓縮比率高的格式。而最需要注意的是圖片的壓縮忱嘹,圖片的壓縮嘱腥,分為幾個(gè)部分

1.Compress PNG Files?打包的時(shí)候自動(dòng)對圖片進(jìn)行無損壓縮,注意:這個(gè)選項(xiàng)對asset catalog中的資源是無效的拘悦,因?yàn)檫@個(gè)選項(xiàng)僅適用于零散資源文件齿兔。

2.?Remove Text Medadata From PNG Files??移除 PNG 資源的文本字符

3.針對普通圖片,可以調(diào)用tinyPNG API進(jìn)行壓縮?

4.放入xcassets里的2x和3x圖片,在上傳時(shí)分苇,會(huì)根據(jù)具體設(shè)備分開對應(yīng)分辨率的圖片添诉,不會(huì)同時(shí)包含。而放入Bundle中的都會(huì)包含医寿。所以要盡量把圖片放入xcassets中栏赴。使用頻率高且小的圖片放到Asset.car中,Asset.car能保證加載和渲染速度最優(yōu)靖秩。但是大的圖片(大于100K)就不要放入Asset.car中了须眷。大的圖片可以考慮將圖片轉(zhuǎn)成WebP。

5. 將PNG 格式轉(zhuǎn) WebP沟突,WebP 壓縮率高花颗,而且肉眼看不出差異,同時(shí)支持有損和無損兩種壓縮模式惠拭。有損壓縮模式下可減少 64% 大小扩劝,無損壓縮模式下可減少 19% 大小,可使用iSparta進(jìn)行批量轉(zhuǎn)換职辅。注意:WebP在 CPU 消耗和解碼時(shí)間上會(huì)比 PNG 高兩倍棒呛,所以適合小圖。

6.Pod庫中的資源文件,推薦使用resource_bundles配合xcassets的方式來集成各個(gè)插件中的資源文件,即xcassets需要添加到podspec的resource_bundles中罐农,Pod庫中的代碼在讀取圖片資源時(shí)条霜,使用imageNamed:inBundle:compatibleWithTraitCollection:讀取,而不是imageNamed:讀取涵亏。但如果pod中有資源文件沒有用xcassets宰睡,那這些資源文件必須放入resource_bundles中,禁止放入resource中气筋;(resource_bundle中的資源在構(gòu)建期能經(jīng)過Xcode的優(yōu)化拆内,而resource中的資源不能)

這樣做的優(yōu)點(diǎn)有:

(1)各個(gè)pod管理各自的資源文件,不會(huì)有命名沖突的問題

(2)能利用蘋果的app slicing功能 宠默,下面我會(huì)講這個(gè)

資源文件優(yōu)化總結(jié)如下:

asset_optimization_summary

延伸一個(gè)知識點(diǎn)麸恍,蘋果官方的app slicing ,在以上一系列優(yōu)化過程中,我們僅僅關(guān)注了內(nèi)部平臺(tái)構(gòu)建出的安裝包的包大小搀矫,而忽視了apple已經(jīng)為我們提供了官方的解決方案抹沪。app slicing是iOS9增加的功能。當(dāng)用戶從app store上下載app時(shí)瓤球,可以只下載適用于其設(shè)備的app架構(gòu)版本和所需資源(如2x和3x設(shè)備)融欧,從而減少app所占的空間。如果開發(fā)者想要使用app slicing卦羡,只需要將資源文件用Asset Catalog管理噪馏,不需要做額外的任何事情麦到。所以一頓操作發(fā)現(xiàn),蘋果已經(jīng)為開發(fā)者尋求到了一個(gè)較優(yōu)的解決方案欠肾。

寫在最后

瘦身完成之后瓶颠,如何保證包大小不會(huì)再次迅速增大?就需要依賴適當(dāng)?shù)谋O(jiān)控機(jī)制和合理的流程規(guī)范來控制刺桃。

監(jiān)控機(jī)制保證實(shí)時(shí)發(fā)現(xiàn)問題粹淋,每次打包完成后比較包大小差異

流程規(guī)范是用于保證每個(gè)項(xiàng)目開發(fā)者知曉開發(fā)中注意什么,養(yǎng)成好的開發(fā)習(xí)慣瑟慈,避免造成包大小的突然變大廓啊。如:

1.引入新的三方庫時(shí),要考慮是否已有同類型的庫封豪,是否可以自己實(shí)現(xiàn),是否會(huì)造成體積增大炒瘟。盡量避免Objective-C和Swift混編吹埠,優(yōu)先引用相同語言類型的庫;

2.新增的圖片資源疮装,關(guān)注大小缘琅,是否能代碼實(shí)現(xiàn),注意放入項(xiàng)目的位置廓推,如果體積太大刷袍,壓縮后使用;

3.廢棄模塊或者業(yè)務(wù)代碼不要保留樊展,及時(shí)清理呻纹。畢竟git有記錄;

4.?及時(shí)關(guān)注包大小變化.

引用

1.深入探索 iOS 包體積優(yōu)化

2.今日頭條 iOS 安裝包大小優(yōu)化—— 新階段专缠、新實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雷酪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涝婉,更是在濱河造成了極大的恐慌哥力,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墩弯,死亡現(xiàn)場離奇詭異吩跋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)渔工,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門锌钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涨缚,你說我怎么就攤上這事轧粟〔咧危” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵兰吟,是天一觀的道長通惫。 經(jīng)常有香客問我,道長混蔼,這世上最難降的妖魔是什么履腋? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮惭嚣,結(jié)果婚禮上遵湖,老公的妹妹穿的比我還像新娘。我一直安慰自己晚吞,他們只是感情好延旧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著槽地,像睡著了一般迁沫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捌蚊,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天集畅,我揣著相機(jī)與錄音,去河邊找鬼缅糟。 笑死挺智,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窗宦。 我是一名探鬼主播赦颇,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迫摔!你這毒婦竟也來了沐扳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤句占,失蹤者是張志新(化名)和其女友劉穎沪摄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纱烘,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杨拐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了擂啥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哄陶。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哺壶,靈堂內(nèi)的尸體忽然破棺而出屋吨,到底是詐尸還是另有隱情蜒谤,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布至扰,位于F島的核電站鳍徽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏敢课。R本人自食惡果不足惜阶祭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望直秆。 院中可真熱鬧濒募,春花似錦、人聲如沸圾结。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筝野。三九已至培他,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遗座,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工俊扳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留途蒋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓馋记,卻偏偏與公主長得像号坡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子梯醒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容