iOS-使用python脚本替换方法引用同时修改导入的头文件

背景

iOS项目废弃旧的类及方法引用,替换成新的类及新的方法, 如果调用较多, 手动替换将是一件费时费力且容易出错的事情,交给脚本就轻松多了

归根结底, 懒惰是第一生产力

实现效果

  • 替换旧的方法引用为新的方法引用
  • 删除旧的方法需要导入的头文件
  • 新增新的方法需要导入的头文件, 放在当前类所有import的最后一行
  • 同一个类不会重复导入相同的头文件
  • 若和pod目录平级,不会修改pod目录下的文件
  • 终端打印修改的内容和行数

使用方式

  1. 脚本需要放在与要替换的工程代码最外层文件夹平级

    eg:
    iOS-使用python脚本替换方法引用同时修改导入的头文件_第1张图片
    20190827165629.png
  1. cd该目录,执行语句
python replaceMethod.py '要废弃的方法调用' '新的方法调用' '要废弃的方法调用的头文件导入' '新的方法调用的头文件导入'

eg : 要替换 [JYUserInfoManager userToken]
引用为 JYLoginMaintUser.token

因为 [JYUserInfoManager userToken] 需要导入头文件 #import

JYLoginMaintUser.token 需要导入头文件
#import

执行

python replaceMethod.py '[JYUserInfoManager userToken]' 'JYLoginMaintUser.token' '#import ' '#import '

脚本源码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#0.1.0
import os
import sys
import os.path
import shutil

def main():
    methodName = sys.argv[1]
    newMethodName =  sys.argv[2]
    removeName = sys.argv[3]
    importName = sys.argv[4]
    print ('methodName:',  methodName )
    print ('newMethodName:',  methodName )
    print ('importName:',  importName)
    print ('removeName:',  removeName)

    # os.getcwd() 方法用于返回当前工作目录
    current_path = os.getcwd()
    print('ℹ️  脚本所在路径:' + current_path)

    code_files = []
    #1. 找到除了Pods文件夹下的代码文件
    for root, dirs, files in os.walk(current_path):
        for file in files:
            # 找到所有类
            if os.path.splitext(file)[1] == '.m' or  os.path.splitext(file)[1] == '.mm' :
                
                code_file_path = os.path.join(root,file)
                #如果文件是在pods中,就忽略掉
                if code_file_path.find('/Pods/')<0:
                    code_files.append(code_file_path)
                    


    print('类的总数: %d'  %len(code_files))


    print('ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️  获取含有' + methodName + '方法的类 ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️ ℹ️  ')
    print('\n')


   #2. 找到所有包含原方法的类 
    methodClassList = []

    for code_file in code_files:
        read_file = open(code_file)
        file_contents = read_file.read()
        read_file.close()

        method_file_list = file_contents.split('\n')

        for method_file in method_file_list:
            if methodName in method_file:
                if code_file not in methodClassList:
                   methodClassList.append(code_file)
                   print('ℹ️  包含该方法的类:' + code_file)


    print('包含该方法类的总数: %d'  %len(methodClassList)) 

    #3. 找到该方法, 替换成新的方法
    for code_file in methodClassList:
        read_file = open(code_file)
        file_contents = read_file.readlines()
        read_file.close()

        write_file = open(code_file, "w")
        for line in file_contents:
            if methodName in line:
                line =  line.replace(methodName,newMethodName)
                print('ℹ️  替换:' + methodName + '为' + newMethodName)
                print('-----line:' + line)
            write_file.write(line)
        write_file.close()


#4. 删除原本导入的头文件
    for code_file in methodClassList:
        read_file = open(code_file)
        file_contents = read_file.readlines()
        read_file.close()

        write_file = open(code_file, "w")
        for line in file_contents:
            if removeName in line:
                continue
            write_file.write(line)
        write_file.close()



#5.添加需要导入的头文件 
    for code_file in methodClassList:
        read_file = open(code_file)
        file_contents = read_file.read()
        read_file.close()

         #循环获取 #import数组
        import_file_list = file_contents.split('\n')

        line = 0
        maxline = 0;  #在最后一行import 后导入头文件
        for import_file in import_file_list:
            line = line + 1
            if '#import' in import_file:
                 if maxline < line:
                     maxline = line;
                 # print('ℹ️  包含该方法的类:' + code_file)
                 # print('import_file:    ', import_file)
                 # print('行数:    ', line)
        print('ℹ️  包含该方法的类:' + code_file)         

        checkSelfResult =   checkSelf(code_file, importName)
        if checkSelfResult == False:
            if importName not in  import_file_list:
                 writeinfile(code_file, importName, maxline + 1)

#判断是否是要import的类本身
def checkSelf (code_file, importName):
    #导入pod中库 忽略
    if  '#import<' in  importName.replace(" ", "") : 
        return False
    import_class_name =  importName.replace(" ", "").split('#import"')[1].split('.h')[0]  

    if(import_class_name in code_file):
        return True
    else :
        return False


 #写入文件
def writeinfile(path, content, line=0):
    lines = []
    with open(path, 'r') as r:
        for l in r:
            lines.append(l)
    if line == 0:
        lines.insert(0, '{}\n'.format(content))
    else:
        lines.insert(line-1, '{}\n'.format(content))
    s = ''.join(lines)

    with open(path, 'w') as m:
        m.write(s)
        print('写入 :' + content)
        print('写入行数: %d' %line)
        m.close()       

if __name__ == '__main__':
    main()

写在最后

完全业余写法, 仅用于限于使用, 不建议学习

你可能感兴趣的:(iOS-使用python脚本替换方法引用同时修改导入的头文件)