Python-一鍵查找iOS項目中未使用的圖片、音頻、視頻資源

前言

在iOS項目開發的過程中,如果版本迭代開發的時間比較長,那麼在很多版本開發以後或者說有多人開發參與以後,工程中難免有一些垃圾資源,未被使用卻佔據着api包的大小!

這裏我通過Python腳本來查找項目中未被使用的圖片、音頻、視頻資源,然後刪除掉;以達到減小APP包大小的目的!

代碼

先查找項目中所以的資源文件存到你數組裏面

def searchAllResName(file_dir):
    global _resNameMap
    fs = os.listdir(file_dir)
    for dir in fs:
        tmp_path = os.path.join(file_dir, dir)
        if not os.path.isdir(tmp_path):
            if isResource(tmp_path) == True and '/Pods/' not in tmp_path and '.appiconset' not in tmp_path and '.launchimage' not in tmp_path:
                imageName = tmp_path.split('/')[-1].split('.')[0]
                _resNameMap[imageName] = tmp_path
                conLog.info_delRes('[FindRes OK] ' + tmp_path)
 
        elif os.path.isdir(tmp_path) and tmp_path.endswith('.imageset') and '/Pods/' not in tmp_path:
            imageName = tmp_path.split('/')[-1].split('.')[0]
            _resNameMap[imageName] = tmp_path
            conLog.info_delRes('[FindRes OK] ' + tmp_path)
 
        else:
            searchAllResName(tmp_path)

遍歷查詢項目的所以代碼,查找工程中所引用的資源文件

# 查詢項目的所以代碼
def searchProjectCode(file_dir):
    global _projectPbxprojPath
    fs = os.listdir(file_dir)
    for dir in fs:
        tmp_path = os.path.join(file_dir, dir)
        if tmp_path.endswith('project.pbxproj'):
            _projectPbxprojPath = tmp_path
 
        if not os.path.isdir(tmp_path):
            if '/Pods/' not in tmp_path:
                try:
                    findResNameAtFileLine(tmp_path)
                    conLog.info_delRes('[ReadFileForRes OK] ' + tmp_path)
                except Exception as e:
                    pass
                    # conLog.error_delRes('[ReadFileForRes Fail] [' + str(e) + ']' + tmp_path)
        else:
            searchProjectCode(tmp_path)
 
# 查找工程中所引用的資源文件
def findResNameAtFileLine(tmp_path):
    global _resNameMap
    Ropen = open(tmp_path,'r')
    for line in Ropen:
        lineList = line.split('"')
        for item in lineList:
            # bar@2x barimg.png
            if item in _resNameMap or item.split('.')[0] in _resNameMap or item + '@1x' in _resNameMap or item + '@2x' in _resNameMap or item + '@3x' in _resNameMap:
                del _resNameMap[item]
 
    Ropen.close()

刪除垃圾資源文件,這裏垃圾資源文件刪除分爲兩部分一部分是Assets.xcassets裏面的,一部分是直接導入工程目錄中的資源,如果是Assets.xcassets垃圾資源直接刪除就行了,但是如果是直接導入到工程目錄裏面的資源,那就先刪除project.pbxproj中的引用,再刪除本地資源文件;

# 刪除無用的資源文件
def delAllRubRes():
    global _resNameMap, _hadDelMap
    # .imageset類型的資源圖片直接刪除
    for resName in list(_resNameMap.keys()):
        tmp_path = _resNameMap[resName]
        if tmp_path.endswith('.imageset'):
            if os.path.exists(tmp_path) and os.path.isdir(tmp_path):
                try:
                    # 已刪除的元素
                    _hadDelMap[resName] = tmp_path
                    # 刪除.imageset文件夾
                    delImagesetFolder(tmp_path)
                    # 字典移除
                    del _resNameMap[resName]
                    conLog.info_delRes('[DelRubRes OK] ' + tmp_path)
                except Exception as e:
                    conLog.error_delRes('[DelRubRes Fail] [' + str(e) + ']' + tmp_path)
            else:
                conLog.error_delRes('[DelRubRes Fail] [not exists] ' + tmp_path)
 
    delResAtProjectPbxproj()
 
def delImagesetFolder(rootdir):
    filelist = []
    filelist = os.listdir(rootdir)
    for f in filelist:
        filepath = os.path.join( rootdir, f )
        if os.path.isfile(filepath):
            os.remove(filepath)
        elif os.path.isdir(filepath):
            shutil.rmtree(filepath,True)
    shutil.rmtree(rootdir,True)
        
# 直接導入到工程中的圖片需要刪除project.pbxproj中的引用,再移除本地文件
def delResAtProjectPbxproj():
    global _projectPbxprojPath, _resNameMap, _hadDelMap
    if _projectPbxprojPath != None:
        # 先把需要刪除的資源名先保存一份
        _needDelResName = []
        file_data = ''
        Ropen = open(_projectPbxprojPath,'r')
        for line in Ropen:
            idAdd = True
            for resName in _resNameMap:
                if resName in line:
                    idAdd = False
                    if resName not in _needDelResName:
                        _needDelResName.append(resName)
 
            if idAdd == True:
                file_data += line
 
        Ropen.close()
        Wopen = open(_projectPbxprojPath,'w')
        Wopen.write(file_data)
        Wopen.close()
        # 已經清理過project.pbxproj中的引用的資源文件,開始從_resNameMap中移除已被處理過的資源文件
        # 並刪除本地的對應的資源文件
        for item in _needDelResName:
            tmp_path = _resNameMap[item]
            if os.path.exists(tmp_path) and not os.path.isdir(tmp_path):
                # 已刪除的元素
                _hadDelMap[item] = tmp_path
                # 刪除文件
                os.remove(tmp_path)
                # 字典移除
                del _resNameMap[item]
                conLog.info_delRes('[DelRubRes OK] ' + tmp_path)
            else:
                pass

總的調用函數

# 開始清理無用的垃圾資源文件
def startCleanRubRes(file_dir, ignoreList = []):
    global _resNameMap, _hadDelMap,_isCleaing
    if _isCleaing == True:
        return
    _isCleaing = True
    initData()
    conLog.info('-' * 30 + '開始清理資源文件' + '-' * 30)
    searchAllResName(file_dir)
    conLog.info_delRes('-' * 20 + '全部的資源文件列表' + '-' * 20)
    conLog.info_delRes(_resNameMap)
    for item in ignoreList:
        if item in list(_resNameMap.keys()):
            del _resNameMap[item]
    conLog.info_delRes('-' * 20 + '忽略刪除的資源文件' + '-' * 20)
    conLog.info_delRes(ignoreList)
    searchProjectCode(file_dir)
    conLog.info_delRes('-' * 20 + '需要刪除的資源文件' + '-' * 20)
    conLog.info_delRes(_resNameMap)
    delAllRubRes()
    conLog.info_delRes('-' * 20 + '刪除成功的資源文件' + '-' * 20)
    conLog.info_delRes(_hadDelMap)
    conLog.info_delRes('-' * 20 + '刪除失敗的資源文件' + '-' * 20)
    conLog.info_delRes(_resNameMap)
    _isCleaing = False

軟件

鑑於有些iOS開發程序員沒有Python基礎,這裏做了一個圖形化操作界面,歡迎大家下載使用!

下載地址:

https://gitee.com/zfj1128/ZFJ...

軟件截圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章