iOS-APP瘦身

屏幕快照 2016-07-15 上午10.47.09.png

資源優(yōu)化

1. 去除無用資源

一般都是版本迭代過程中存在的圖片資源喂窟。
可以借助三方工具來解決: Unused-master LSUnusedResources

通過Unused-master可以查找到一些工程中沒有用到的圖片,但這個工具并不是百分百正確揪垄,在圖片刪除的時候要慎重看一下遵蚜。在掃描結果中扒腕,查找到了一些命名錯誤的圖片吧彪,例如:xxx2x.png、xxx.png這樣的圖片命名方式會影響APP性能

D3BEE3F9-029C-41E3-B704-772A3EA0EB0A.png
2. 資源壓縮
2.1. 圖片無損壓縮

這個主要是利用三方工具ImageOptim來實現(xiàn):

屏幕快照 2016-07-04 下午1.54.17.png

ImageOptim Mac版是一款非常簡單的圖片大小優(yōu)化工具出刷。只要拖動圖片到軟件界面就可以自動把圖片的大小進行優(yōu)化璧疗。ImageOptim Mac版對于開發(fā)人員和設計人員一定還有用處,如文件的EXIF標簽和顏色配置文件等馁龟,達到優(yōu)化減小占用磁盤空間崩侠。

圖片文件中往往包含一些注釋、顏色 Profile 等多余信息屁柏,移除后圖像質量不變啦膜,體積更小載入更快有送。ImageOptim 以此方式壓縮圖片,先分析圖片僧家,找到最優(yōu)壓縮參數(shù)雀摘,去除無關信息減小體積贯莺,實行無損壓縮襟衰。

62B4D991-1827-491C-9FC9-C9C94C6C5567.png

關于圖片資源補充:

1.能用縮略圖的用縮略圖、單一色彩可以用純色代替
2.盡量使用8-bit圖片使用8-bit的PNG圖片鹤啡,比32-bit的圖片能減少4倍的壓縮率肌稻。 由于8-bit的圖片支持最多256種不同的顏色清蚀,所以8-bit的圖片一般只應該用于一小 部分的顏色圖片。例如灰度圖片最好使用8-bit爹谭。

2.2. 音頻壓縮

參考WWDC中的Audio Development for Games枷邪,里面介紹了如何有效的處理音頻。常規(guī)來說诺凡,我們要使用AAC或MP3來壓縮音頻东揣,并且可以嘗試降低一下音頻的比特率。有時候44.1khz的采樣是沒有必要的腹泌,稍微低一點的比特率也不會降低音頻的質量嘶卧。

2.3. 查找文件大小

通過查找工程中文件的大小,可以找到一些較大的圖片和三方庫凉袱,視情況壓縮或替換這個主要是用命令行芥吟,cd到工程目錄 然后輸入find . -size +100 就會遍歷出工程目錄下大于100k的文件,如果是+1000 就是大于1000k的专甩,以此類推...
例如:Robin:SimpleFinance zhaojijin$ find . -size +1000

0F7BB855-3C4F-424E-B1C5-788B53FC107A.png

這個方法掃描到的文件并不是完全正確钟鸵,如上圖,這個結果中changeCard_lostCardStepOnePic@3x.png finder中實際大小是854k配深,但這并不影響使用携添,大體還是對的

3.不常用資源換為下載

比如自定義字體,可以在APP第一次啟動后動態(tài)獲取

編譯優(yōu)化

1. 去除符號信息

Strip Debug Symbols During Copy 和 Symbols Hidden by Default 在release版本應該設為yes篓叶,可以去除不必要的調試符號,當然xcode默認就是yes

2. 開啟編譯優(yōu)化

Build Settings->Optimization Level有幾個編譯優(yōu)化選項,release版應該選擇Fastest, Smalllest羞秤,這個選項會開啟那些不增加代碼大小的全部優(yōu)化缸托,并讓可執(zhí)行文件盡可能小。

3. 避免編譯多個框架(但多個框架在不同機型上運行速度相對快點,iOS9 app thinning)

如果應用需要在多種cpu架構下運行瘾蛋,那么xcode生成的二進制文件會包含對應架構的多個副本俐镐,這樣可執(zhí)行文件的大小就會成倍增加。
arm cpu架構可以標識為armvX (64)哺哼,X代表一個數(shù)字佩抹,如果不指定是64位叼风,就是指32位。一般來說arm架構都是向后兼容的棍苹,armv6的代碼可以在armv7上運行无宿,32位的代碼可以在64位cpu上運行。(buidsettings->Architectures)

可執(zhí)行文件優(yōu)化

在項目里新建一個類枢里,給它添加幾個方法孽鸡,但不要在任何地方import它,build完項目后觀察linkmap栏豺,你會發(fā)現(xiàn)這個類還是被編譯進可執(zhí)行文件了彬碱。
linkmap文件是xcode link時產生的中間文件,一般用于調試奥洼,可以精確知道某個地址對應的函數(shù)巷疼。
對此我們可以通過腳本,遍歷整個項目的文件灵奖,找出所有沒有被引用的類文件和沒有被調用的方法嚼沿,在保證沒有其他地方動態(tài)調用的情況下把它們去掉。如果整個項目歷時很長桑寨,歷時代碼遺留較多伏尼,這個清理對可執(zhí)行文件省出的空間還是挺可觀的。

可執(zhí)行文件的組成

XCode開啟編譯選項Write Link Map File
XCode -> Project -> Build Settings -> 搜map -> 把Write Link Map File選項設為yes尉尾,并指定好linkMap的存儲位置

屏幕快照 2016-07-05 下午6.08.47.png

編譯后爆阶,到編譯目錄里找到該txt文件,文件名和路徑就是上述的Path to Link Map File位于~/Library/Developer/Xcode/DerivedData/XXX-eumsvrzbvgfofvbfsoqokmjprvuh/Build/Intermediates/XXX.build/XXX-iphoneos/XXX.build/XXX-LinkMap-normal-armXX.text
其中XXX-eumsvrzbvgfofvbfsoqokmjprvuh的命名是不確定的這個LinkMap里展示了整個可執(zhí)行文件的全貌沙咏,列出了編譯后的每一個.o目標文件的信息(包括靜態(tài)鏈接庫.a里的)辨图,以及每一個目標文件的代碼段,數(shù)據(jù)段存儲詳情肢藐。

1.在LinkMap里首先列出來的是目標文件列表:

[0] linker synthesized
[1] /Users/zhaojijin/Library/Developer/Xcode/DerivedData/SimpleFinance-cvxujvtykofyxphauukoxkqhstcn/Build/Intermediates/SimpleFinance.build/Release-iphoneos/SimpleFinance.build/Objects-normal/arm64/UIImageView+HighlightedWebCache.o
[2] /Users/zhaojijin/Library/Developer/Xcode/DerivedData/SimpleFinance-cvxujvtykofyxphauukoxkqhstcn/Build/Intermediates/SimpleFinance.build/Release-iphoneos/SimpleFinance.build/Objects-normal/arm64/YKHomeWaitToBeMatchTitleItem.o

...

[1217] /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/usr/lib/libobjc.tbd
[1218] /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/usr/lib/libSystem.tbd
[1219] /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks//Accelerate.framework/Accelerate.tbd

前面中括號里的是這個文件的編號故河,后面會用到,像項目里引用到靜態(tài)鏈接庫里的目標文件都會在這里列出來吆豹。

2.接著是一個段表鱼的,描述各個段在最后編譯成的可執(zhí)行文件中的偏移位置及大小,包括了代碼段(__TEXT痘煤,保存程序代碼段編譯后的機器碼)和數(shù)據(jù)段(__DATA凑阶,保存變量值)

    # Sections:
    # Address   Size        Segment Section
    0x100006660 0x0049CA0C  __TEXT  __text
    0x1004A306C 0x00002424  __TEXT  __stubs
    0x1004A5490 0x00002418  __TEXT  __stub_helper
    0x1004A78A8 0x00017790  __TEXT  __gcc_except_tab
    0x1004BF038 0x0005A3E7  __TEXT  __objc_methname
    0x100519420 0x00055D9C  __TEXT  __cstring
    0x10056F1BC 0x000082C0  __TEXT  __objc_classname
    0x10057747C 0x0000A9B8  __TEXT  __objc_methtype
    0x100581E40 0x0001BAE8  __TEXT  __const
    0x10059D928 0x0000436E  __TEXT  __ustring
    0x1005A1C98 0x0001235C  __TEXT  __unwind_info
    0x1005B4000 0x000006A8  __DATA  __got
    0x1005B46A8 0x00001818  __DATA  __la_symbol_ptr
    0x1005B5EC0 0x0001B710  __DATA  __const
    0x1005D15D0 0x0003B900  __DATA  __cfstring
    0x10060CED0 0x00002988  __DATA  __objc_classlist
    0x10060F858 0x00000028  __DATA  __objc_nlclslist
    0x10060F880 0x00000320  __DATA  __objc_catlist
    0x10060FBA0 0x00000018  __DATA  __objc_nlcatlist
    0x10060FBB8 0x000003D8  __DATA  __objc_protolist
    0x10060FF90 0x00000008  __DATA  __objc_imageinfo
    0x10060FF98 0x000FFB30  __DATA  __objc_const
    0x10070FAC8 0x000145F0  __DATA  __objc_selrefs
    0x1007240B8 0x00000080  __DATA  __objc_protorefs
    0x100724138 0x00002A28  __DATA  __objc_classrefs
    0x100726B60 0x00001B30  __DATA  __objc_superrefs
    0x100728690 0x00005814  __DATA  __objc_ivar
    0x10072DEA8 0x00019FA0  __DATA  __objc_data
    0x100747E48 0x00002E20  __DATA  __data
    0x10074AC68 0x00002120  __DATA  __bss
    0x10074D000 0x00000800  __DATA  __common

首列是數(shù)據(jù)在文件的偏移位置,第二列是這一段占用大小衷快,第三列是段類型宙橱,代碼段和數(shù)據(jù)段,第四列是段名稱。

每一行的數(shù)據(jù)都緊跟在上一行后面师郑,如第二行__symbol_stub的地址0x00275FD0就是第一行__text的地址0x00002740加上大小0x00273890环葵,整個可執(zhí)行文件大致數(shù)據(jù)分布就是這樣。

這里可以清楚看到各種類型的數(shù)據(jù)在最終可執(zhí)行文件里占的比例宝冕,例如__text表示編譯后的程序執(zhí)行語句张遭,__data表示已初始化的全局變量和局部靜態(tài)變量,__bss表示未初始化的全局變量和局部靜態(tài)變量猬仁,__cstring表示代碼里的字符串常量帝璧,等等。

3.接著就是按上表順序湿刽,列出具體的按每個文件列出每個對應字段的位置和占用空間

    # Address   Size        File  Name
    0x100006660 0x00000018  [  1] -[UIImageView(HighlightedWebCache) sd_setHighlightedImageWithURL:]
    0x100006678 0x00000014  [  1] -[UIImageView(HighlightedWebCache) sd_setHighlightedImageWithURL:options:]
    0x10000668C 0x00000058  [  1] -[UIImageView(HighlightedWebCache) sd_setHighlightedImageWithURL:completed:]
    0x1000066E4 0x0000005C  [  1] -[UIImageView(HighlightedWebCache) sd_setHighlightedImageWithURL:options:completed:]
    ...

同樣首列是數(shù)據(jù)在文件的偏移地址的烁,第二列是占用大小,第三列是所屬文件序號诈闺,對應上述Object files列表渴庆,最后是名字。

1. 去除無用代碼

在項目里新建一個類雅镊,給它添加幾個方法襟雷,但不要在任何地方import它,build完項目后觀察linkmap仁烹,你會發(fā)現(xiàn)這個類還是被編譯進可執(zhí)行文件了耸弄。
對此我們可以通過腳本,遍歷整個項目的文件卓缰,找出所有沒有被引用的類文件和沒有被調用的方法计呈,在保證沒有其他地方動態(tài)調用的情況下把它們去掉。如果整個項目歷時很長征唬,歷時代碼遺留較多捌显,這個清理對可執(zhí)行文件省出的空間還是挺可觀的。

2. 統(tǒng)計庫占用

項目里會引入很多第三方靜態(tài)庫总寒,如果能知道這些第三方庫在可執(zhí)行文件里占用的大小扶歪,就可以評估是否值得去找替代方案去掉這個第三方庫。我們可以從linkmap中統(tǒng)計出這個信息摄闸,利用三方的node.js腳本善镰,可以通過linkmap統(tǒng)計每個.o目標文件占用的體積和每個.a靜態(tài)庫占用的體積,并進行排序

3. 混淆類/方法名

觀察linkmap可以發(fā)現(xiàn)每個類和方法名都在__cstring段里都存了相應的字符串值年枕,所以類和方法名的長短也是對可執(zhí)行文件大小是有影響的媳禁,原因還是object-c的動態(tài)特性,因為需要通過類/方法名反射找到這個類/方法進行調用画切,object-c對象模型會把類名,方法名列表都保存下來囱怕。
可以考慮在編譯前把所有類和方法名進行混淆霍弹,把長名字替換成短名字毫别,這樣做的好處除了縮小體積外,還對安全性有很大提升典格,別人拿到可執(zhí)行文件對它class-dump出來的結果都是混淆后的類和方法名岛宦,就無法從類和方法名中猜出某個方法是做什么的,就難以掛鉤子進行hack耍缴。不過這樣有個缺點就是crash堆棧反解出來的堆棧方法名會是混淆后的砾肺,需要再加一層混淆->原名的轉換,實現(xiàn)和使用成本有點高防嗡。

4. 減少冗余字符串

代碼上定義的所有靜態(tài)字符串都會記錄在在可執(zhí)行文件的__cstring段变汪,如果項目里Log非常多,這個空間占用也是可觀的蚁趁,也有幾百K的大小裙盾,可以考慮清理所有冗余的字符串。另外如果有特別長的字符串他嫡,建議抽離保存成靜態(tài)文件番官,因為AppStore對可執(zhí)行文件加密導致壓縮率低,特別長的字符串抽離成靜態(tài)資源文件后壓縮率會比在可執(zhí)行文件里高很多钢属。
替換NSLog為DLog:

image.png

類徘熔、方法名、屬性名等命名長短影響包大小:

91FF2BF6-D5C3-4F00-89BC-ED4D6A3CD15F.png
5. ARC->MRC降低8%空間占用(可忽略淆党,不實用)
image.png

homebrew

Homebrew官網(wǎng)

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
參考:

iOS工程瘦身

iOS微信安裝包瘦身

iOS可執(zhí)行文件瘦身方法

iOS 對源代碼進行混淆

iOS APP可執(zhí)行文件的組成

用OCLint給iOS代碼做靜態(tài)分析

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末酷师,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宁否,更是在濱河造成了極大的恐慌窒升,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慕匠,死亡現(xiàn)場離奇詭異饱须,居然都是意外死亡,警方通過查閱死者的電腦和手機台谊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門蓉媳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锅铅,你說我怎么就攤上這事酪呻。” “怎么了盐须?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵玩荠,是天一觀的道長。 經常有香客問我,道長阶冈,這世上最難降的妖魔是什么闷尿? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮女坑,結果婚禮上填具,老公的妹妹穿的比我還像新娘。我一直安慰自己匆骗,他們只是感情好劳景,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著碉就,像睡著了一般盟广。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铝噩,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天衡蚂,我揣著相機與錄音,去河邊找鬼骏庸。 笑死毛甲,一個胖子當著我的面吹牛,可吹牛的內容都是我干的具被。 我是一名探鬼主播玻募,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼一姿!你這毒婦竟也來了七咧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤叮叹,失蹤者是張志新(化名)和其女友劉穎艾栋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛉顽,經...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡蝗砾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了携冤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悼粮。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖曾棕,靈堂內的尸體忽然破棺而出扣猫,到底是詐尸還是另有隱情,我是刑警寧澤翘地,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布申尤,位于F島的核電站癌幕,受9級特大地震影響,放射性物質發(fā)生泄漏瀑凝。R本人自食惡果不足惜序芦,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粤咪。 院中可真熱鬧,春花似錦渴杆、人聲如沸寥枝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囊拜。三九已至,卻和暖如春比搭,著一層夾襖步出監(jiān)牢的瞬間冠跷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工身诺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蜜托,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓霉赡,卻偏偏與公主長得像橄务,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子穴亏,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內容

  • 文章最后有我的 12 條小總結蜂挪。 寫在前面 最近公司需求不多,正好研究一下 App 瘦身的辦法嗓化,寫了點小總結棠涮。 如...
    Damonwong閱讀 7,710評論 14 76
  • 縮減iOS安裝包大小是很多中大型APP都要做的事,一般首先會對資源文件下手刺覆,壓縮圖片/音頻严肪,去除不必要的資源。這些...
    buptwsg閱讀 1,972評論 0 8
  • 更多內容請挪步我的博客 圖片資源刪減 使用工具查找未引用資源 LSUnusedResources 比之前的 Unu...
    AliciaRain閱讀 675評論 1 0
  • iOS App瘦身 關于app瘦身隅津,你能想到什么诬垂? 刪除無用類 刪除無用方法 代碼相似度分析 刪除無用圖片 無損壓...
    碼農二哥閱讀 450評論 2 3
  • 《必然》第二章 知化(一) 知化:賦予對象認知能力。 從目前人工智能技術的發(fā)展速度來看伦仍,現(xiàn)在出生的孩子在成年后可能...
    日子林光閱讀 503評論 3 2