iOS 工程瘦身

app在3.0版本時(shí)安裝包已達(dá)到66.1M,app瘦身刻不容緩益眉。 App安裝包是由資源和可執(zhí)行文件兩部分組成,安裝包瘦身也是從這兩部分進(jìn)行关摇。

1.工程資源文件瘦身

工程資源文件主要是圖片,資源大小與圖片質(zhì)量和數(shù)量息息相關(guān)。

分析圖片的數(shù)量,質(zhì)量

使用腳本獲取工程中的所有圖片資源终吼,大小。工程共有722張圖片汉买,占用了8.2M的空間衔峰。圖片大小分類如圖:

figure_1.png

其中10k以下占用率絕大部分,但還是有很多圖片超過了100k蛙粘,甚至有一些圖片達(dá)到了1M.太恐怖了垫卤。。出牧。建議把大文件替換穴肘。

圖片文件壓縮
無損壓縮工具ImageOptiom(推薦)。這是一款非常好的圖片壓縮工具舔痕,可以進(jìn)行無損壓縮评抚,能夠?qū)?png 和 jpeg 圖片文件進(jìn)行優(yōu)化,它能找到最佳的壓縮參數(shù)(在設(shè)置中可以設(shè)置壓縮比例伯复,80% 及以上是無損壓縮慨代,推薦使用),并通過消除不必要的信息(如文件的 EXIF 標(biāo)簽和顏色配置文件等)啸如,優(yōu)化后達(dá)到減小文件大小的效果侍匙。

使用了一張950k的圖片經(jīng)過ImageOptiom壓縮后586k,節(jié)省了38.3%的空間。

清除無用的資源文件

推薦使用工具LSUnusedResources叮雳。

接下來想暗,打開工具LSUnusedResources妇汗,點(diǎn)擊“Browse...”按鈕,選擇工程所在目錄说莫,點(diǎn)擊"Search"按鈕杨箭,即可開始搜索,如下圖所示:


屏幕快照 2017-07-05 下午3.47.44.png

工程中有234張圖片未引用储狭,但這個(gè)不準(zhǔn)因?yàn)樗皇轻槍υ创a互婿、Xib、Storyboard 和 plist 等文件晶密,先全文搜索其中可能是引用了資源的字符串擒悬,然后用資源名和字符串做匹配,而拼接的圖片會當(dāng)做未使用的圖片稻艰。因此搜索出后還需開發(fā)確認(rèn)是否是拼接圖片懂牧。

可執(zhí)行文件的瘦身

LinkMap文件是Xcode產(chǎn)生可執(zhí)行文件的同時(shí)生成的鏈接信息,用來描述可執(zhí)行文件的構(gòu)造成分尊勿,包括代碼段(__TEXT)和數(shù)據(jù)段(__DATA)的分布情況僧凤。

在Xcode中,選擇XCode -> Target -> Build Settings -> 搜map -> 把Write Link Map File選項(xiàng)設(shè)為YES元扔,并指定好linkMap的存儲位置躯保。

編譯后,到編譯目錄里找到該txt文件澎语,文件名和路徑就是上述的Path to Link Map File途事。這個(gè)LinkMap里展示了整個(gè)可執(zhí)行文件的全貌,列出了編譯后的每一個(gè).o目標(biāo)文件的信息(包括靜態(tài)鏈接庫.a里的)擅羞,以及每一個(gè)目標(biāo)文件的代碼段尸变,數(shù)據(jù)段存儲詳情。

import os
import re
import shutil
import sys

path = '/Users/mini5/Desktop/SmartHomeV6-LinkMap--.txt'
analyzeAllMoundle = False #統(tǒng)計(jì)每個(gè)模塊.o的統(tǒng)計(jì)大小

class SymbolModel:
    file = ""
    size = 0

def verify_linkmapfile(path):
    if not os.path.isfile(path):
        print("請輸入文件")
        return False

    file = open(path)
    content    = file.read()
    file.close()

    #查找是否存在# Object files:
    if content.find("# Object files:") == -1:
        print("輸入linkmap文件非法")
        return False
    #查找是否存在# Sections:
    if content.find("# Sections:") == -1:
        print("輸入linkmap文件非法")
        return False
    #查找是否存在# Symbols:
    if content.find("# Symbols:") == -1:
        print("輸入linkmap文件非法")
        return False

    return True

def symbolMapFromContent():
    symbolMap = {}
    reachFiles = False
    reachSections = False
    reachSymblos = False
    file = open(path)
    for line in file.readlines():
        if line.startswith("#"):
            if line.startswith("# Object files:"):
                reachFiles = True
            if line.startswith("# Sections:"):
                reachSections = True
            if line.startswith("# Symbols:"):
                reachSymblos = True
        else:
            if reachFiles == True and reachSections == False and reachSymblos == False:
                #查找 files 列表减俏,找到所有.o文件
                location = line.find("]")
                if location != -1:
                    key = line[:location+1]
                    if  symbolMap.get(key) is not None:
                        continue
                    symbol = SymbolModel()
                    symbol.file = line[location + 1:]
                    symbolMap[key] = symbol
            elif reachFiles == True and reachSections == True and reachSymblos == True:
                #'\t'分割成三部分召烂,分別對應(yīng)的是Address,Size和 File  Name
                symbolsArray = line.split('\t')
                if len(symbolsArray) == 3:
                    fileKeyAndName = symbolsArray[2]
                    #16進(jìn)制轉(zhuǎn)10進(jìn)制
                    size = int(symbolsArray[1],16)
                    location = fileKeyAndName.find(']')
                    if location != -1:
                        key = fileKeyAndName[:location + 1]
                        symbol = symbolMap.get(key)
                        if symbol is not None:
                            symbol.size = symbol.size + size
    file.close()

    return symbolMap

def sortSymbol(symbolList):
     return sorted(symbolList, key=lambda s: s.size,reverse = True)

def buildResultWithSymbols(symbols):
    results = ["文件大小\t文件名稱\r\n"]
    totalSize = 0
    for symbol in symbols:
        results.append(calSymbol(symbol))
        totalSize += symbol.size
    results.append("總大小: %.2fM" % (totalSize/1024.0/1024.0))
    return results

def buildCombinationResultWithSymbols(symbols):
    #統(tǒng)計(jì)不同模塊大小
    results = ["庫大小\t庫名稱\r\n"]
    totalSize = 0
    combinationMap = {}

    for symbol in symbols:
        names = symbol.file.split('/')
        name = names[len(names) - 1].strip('\n')
        location = name.find("(")
        if name.endswith(")") and location != -1:
            component = name[:location]
            combinationSymbol = combinationMap.get(component)
            if combinationSymbol is None:
                combinationSymbol = SymbolModel()
                combinationMap[component] = combinationSymbol

            combinationSymbol.file = component
            combinationSymbol.size = combinationSymbol.size + symbol.size
        else:
            #symbol可能來自app本身的目標(biāo)文件或者系統(tǒng)的動(dòng)態(tài)庫
            combinationMap[symbol.file] = symbol
    sortedSymbols = sortSymbol(combinationMap.values())

    for symbol in sortedSymbols:
        results.append(calSymbol(symbol))
        totalSize += symbol.size
    results.append("總大小: %.2fM" % (totalSize/1024.0/1024.0))

    return results

def calSymbol(symbol):
    size = ""
    if symbol.size / 1024.0 / 1024.0 > 1:
        size = "%.2fM" % (symbol.size / 1024.0 / 1024.0)
    else:
        size = "%.2fK" % (symbol.size / 1024.0)
    names = symbol.file.split('/')
    if len(names) > 0:
        size = "%s\t%s" % (size,names[len(names) - 1])
    return size

def analyzeLinkMap():
    if verify_linkmapfile(path) == True:
        print("**********正在開始解析*********")
        symbolDic = symbolMapFromContent()
        symbolList = sortSymbol(symbolDic.values())
        if analyzeAllMoundle:
            results = buildCombinationResultWithSymbols(symbolList)
        else:
            results = buildResultWithSymbols(symbolList)
        for result in results:
            print(result)
        print("***********解析結(jié)束***********")


if __name__ == "__main__":
    analyzeLinkMap()

這里可以統(tǒng)計(jì)每個(gè)文件或每個(gè)庫的大小娃承,該舍棄的舍棄奏夫。

其他方式

清理無用類,無用方法历筝,編譯選項(xiàng)優(yōu)化酗昼,好吧,我懶不想寫了梳猪。麻削。。。碟婆。。惕稻。竖共。。俺祠。公给。

參考鏈接: http://www.cnblogs.com/LeeGof/p/6803146.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蜘渣,隨后出現(xiàn)的幾起案子淌铐,更是在濱河造成了極大的恐慌,老刑警劉巖蔫缸,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腿准,死亡現(xiàn)場離奇詭異,居然都是意外死亡拾碌,警方通過查閱死者的電腦和手機(jī)吐葱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來校翔,“玉大人弟跑,你說我怎么就攤上這事》乐ⅲ” “怎么了孟辑?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔫敲。 經(jīng)常有香客問我饲嗽,道長,這世上最難降的妖魔是什么燕偶? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任喝噪,我火速辦了婚禮,結(jié)果婚禮上指么,老公的妹妹穿的比我還像新娘酝惧。我一直安慰自己,他們只是感情好伯诬,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布晚唇。 她就那樣靜靜地躺著,像睡著了一般盗似。 火紅的嫁衣襯著肌膚如雪哩陕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機(jī)與錄音悍及,去河邊找鬼闽瓢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛心赶,可吹牛的內(nèi)容都是我干的扣讼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼缨叫,長吁一口氣:“原來是場噩夢啊……” “哼椭符!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耻姥,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤销钝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后琐簇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒸健,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年鸽嫂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纵装。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡据某,死狀恐怖橡娄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情癣籽,我是刑警寧澤挽唉,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站筷狼,受9級特大地震影響瓶籽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜埂材,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一塑顺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俏险,春花似錦严拒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至莹痢,卻和暖如春种蘸,著一層夾襖步出監(jiān)牢的瞬間墓赴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工航瞭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诫硕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓刊侯,卻偏偏與公主長得像痘括,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子滔吠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

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