How to find unused images in an Xcode project?

前端 未结 14 1590
旧时难觅i
旧时难觅i 2020-12-07 06:57

Has anyone a one-line to find unused images in an Xcode project? (Assuming all the files are referenced by name in code or the project files - no code generated file names.)

相关标签:
14条回答
  • 2020-12-07 07:49

    I used this framework:-

    http://jeffhodnett.github.io/Unused/

    Works damn well! Only 2 places I saw issues are when image names are from server and when the image asset name is different from the name of the image inside the asset folder...

    0 讨论(0)
  • 2020-12-07 07:49

    I have created a python script to identify the unused images: 'unused_assets.py' @ gist. It can be used like this:

    python3 unused_assets.py '/Users/DevK/MyProject' '/Users/DevK/MyProject/MyProject/Assets/Assets.xcassets'
    

    Here are few rules to use the script:

    • It is important to pass project folder path as first argument, assets folder path as second argument
    • It is assumed that all the images are maintained within Assets.xcassets folder and are used either within swift files or within storyboards

    Limitations in first version:

    • Doesn't work for objective c files

    I will try to improve it over the time, based on feedback, however the first version should be good for most.

    Please find below the code. The code should be self explanatory as I have added appropriate comments to each important step.

    # Usage e.g.: python3 unused_assets.py '/Users/DevK/MyProject' '/Users/DevK/MyProject/MyProject/Assets/Assets.xcassets'
    # It is important to pass project folder path as first argument, assets folder path as second argument
    # It is assumed that all the images are maintained within Assets.xcassets folder and are used either within swift files or within storyboards
    
    """
    @author = "Devarshi Kulshreshtha"
    @copyright = "Copyright 2020, Devarshi Kulshreshtha"
    @license = "GPL"
    @version = "1.0.1"
    @contact = "kulshreshtha.devarshi@gmail.com"
    """
    
    import sys
    import glob
    from pathlib import Path
    import mmap
    import os
    import time
    
    # obtain start time
    start = time.time()
    
    arguments = sys.argv
    
    # pass project folder path as argument 1
    projectFolderPath = arguments[1].replace("\\", "") # replacing backslash with space
    # pass assets folder path as argument 2
    assetsPath = arguments[2].replace("\\", "") # replacing backslash with space
    
    print(f"assetsPath: {assetsPath}")
    print(f"projectFolderPath: {projectFolderPath}")
    
    # obtain all assets / images 
    # obtain paths for all assets
    
    assetsSearchablePath = assetsPath + '/**/*.imageset'  #alternate way to append: fr"{assetsPath}/**/*.imageset"
    print(f"assetsSearchablePath: {assetsSearchablePath}")
    
    imagesNameCountDict = {} # empty dict to store image name as key and occurrence count
    for imagesetPath in glob.glob(assetsSearchablePath, recursive=True):
        # storing the image name as encoded so that we save some time later during string search in file 
        encodedImageName = str.encode(Path(imagesetPath).stem)
        # initializing occurrence count as 0
        imagesNameCountDict[encodedImageName] = 0
    
    print("Names of all assets obtained")
    
    # search images in swift files
    # obtain paths for all swift files
    
    swiftFilesSearchablePath = projectFolderPath + '/**/*.swift' #alternate way to append: fr"{projectFolderPath}/**/*.swift"
    print(f"swiftFilesSearchablePath: {swiftFilesSearchablePath}")
    
    for swiftFilePath in glob.glob(swiftFilesSearchablePath, recursive=True):
        with open(swiftFilePath, 'rb', 0) as file, \
            mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as s:
            # search all the assests within the swift file
            for encodedImageName in imagesNameCountDict:
                # file search
                if s.find(encodedImageName) != -1:
                    # updating occurrence count, if found 
                    imagesNameCountDict[encodedImageName] += 1
    
    print("Images searched in all swift files!")
    
    # search images in storyboards
    # obtain path for all storyboards
    
    storyboardsSearchablePath = projectFolderPath + '/**/*.storyboard' #alternate way to append: fr"{projectFolderPath}/**/*.storyboard"
    print(f"storyboardsSearchablePath: {storyboardsSearchablePath}")
    for storyboardPath in glob.glob(storyboardsSearchablePath, recursive=True):
        with open(storyboardPath, 'rb', 0) as file, \
            mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as s:
            # search all the assests within the storyboard file
            for encodedImageName in imagesNameCountDict:
                # file search
                if s.find(encodedImageName) != -1:
                    # updating occurrence count, if found
                    imagesNameCountDict[encodedImageName] += 1
    
    print("Images searched in all storyboard files!")
    print("Here is the list of unused assets:")
    
    # printing all image names, for which occurrence count is 0
    print('\n'.join({encodedImageName.decode("utf-8", "strict") for encodedImageName, occurrenceCount in imagesNameCountDict.items() if occurrenceCount == 0}))
    
    print(f"Done in {time.time() - start} seconds!")
    
    0 讨论(0)
提交回复
热议问题