Preface
In the process of iOS project development, if the iteration time of version development is relatively long, after many versions development or after many people participate in the development, there are inevitably some garbage resources in the project, which are not used but occupy the size of the api package!
Here I use Python script to find the unused pictures, audio and video resources in the project, and then delete them; in order to reduce the size of the APP package!
Code
Find all the resource files in the project and store them in your array.
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)
Go through all the code that queries the project to find the resource files referenced in the project
# So code to query the project 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) # Find the resource files referenced in the project 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()
Delete the junk resource file, here the junk resource file deletion is divided into two parts: Assets.xcassets, part is directly imported into the project directory resources, if it is Assets.xcassets junk resources directly deleted, but if it is directly imported into the project directory resources, then delete PR first. Reference in oject. pbxproj and delete the local resource file.
# Delete useless resource files def delAllRubRes(): global _resNameMap, _hadDelMap # Direct deletion of resource images of. imageset type 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: # Deleted elements _hadDelMap[resName] = tmp_path # Delete. imageset folder delImagesetFolder(tmp_path) # Dictionary Removal 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) # Images imported directly into the project need to delete references in project.pbxproj and then remove local files def delResAtProjectPbxproj(): global _projectPbxprojPath, _resNameMap, _hadDelMap if _projectPbxprojPath != None: # Save a resource name that needs to be deleted first _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() # The resource files referenced in project.pbxproj have been cleaned up and the processed resource files have been removed from _resNameMap # And delete the local corresponding resource file for item in _needDelResName: tmp_path = _resNameMap[item] if os.path.exists(tmp_path) and not os.path.isdir(tmp_path): # Deleted elements _hadDelMap[item] = tmp_path # Delete files os.remove(tmp_path) # Dictionary Removal del _resNameMap[item] conLog.info_delRes('[DelRubRes OK] ' + tmp_path) else: pass
Total calling function
# Start cleaning up useless garbage resource files def startCleanRubRes(file_dir, ignoreList = []): global _resNameMap, _hadDelMap,_isCleaing if _isCleaing == True: return _isCleaing = True initData() conLog.info('-' * 30 + 'Start cleaning up resource files' + '-' * 30) searchAllResName(file_dir) conLog.info_delRes('-' * 20 + 'List of all resource files' + '-' * 20) conLog.info_delRes(_resNameMap) for item in ignoreList: if item in list(_resNameMap.keys()): del _resNameMap[item] conLog.info_delRes('-' * 20 + 'Ignore deleted resource files' + '-' * 20) conLog.info_delRes(ignoreList) searchProjectCode(file_dir) conLog.info_delRes('-' * 20 + 'Resource files that need to be deleted' + '-' * 20) conLog.info_delRes(_resNameMap) delAllRubRes() conLog.info_delRes('-' * 20 + 'Delete a successful resource file' + '-' * 20) conLog.info_delRes(_hadDelMap) conLog.info_delRes('-' * 20 + 'Delete failed resource files' + '-' * 20) conLog.info_delRes(_resNameMap) _isCleaing = False
Software
Since some iOS programmers do not have Python foundation, we have made a graphical operation interface here. Welcome to download and use it!
Download address:
https://gitee.com/zfj1128/ZFJ...