批量修改OC類名指令碼 -- python

WangKunKun發表於2018-12-21

前言

近日由於種種原因,需要把程式碼裡面的類全部都修改一遍類名。

在網上找了一圈相關的開源庫,沒有發現有合適滿意的,始終都存在一些問題,要麼出現誤修改,要麼把方法名或者屬性名也給修改了等等情況。

於是決定掏出生疏的Python來寫一個。

批量修改類名需要解決四個問題:

    1. 如何取得需要修改的類名?
    1. 如何修改檔案中出現的類名並且不會出現誤改等情況?
    1. 如何修改檔名?
    1. 修改檔名後,如何同步修改project.pbxproj裡面的檔名資訊?

問題一、如何取得需要修改的類名?

想法A:

由於自己前不久寫了一個獲取target對應的編譯以及資原始檔的工具MacPbxprojHelper,利用其來獲取到target對應的類名寫入檔案,然後用python來讀取檔案獲取到需要修改的類名,實時上第一版我也是這麼做的,但是不夠優雅,明明一個指令碼能解決的事,為什麼需要那麼多步操作呢?

想法B:

利用python直接遍歷資料夾獲取類名,沒錯就決定是你了。 其實用python遍歷檔案實現起來特別簡單快捷。但是其中也有可能存在的問題,例如我們的專案中包含有部分資原始檔,而資原始檔的字尾名是不定的,但是實際我們只需要.m以及.mm結尾的檔案字首作為我們的類名,當然其中包含有類目也需要過濾掉。並且考慮到我們具備一些特殊的需求,需要過濾某些檔案甚至某些資料夾下的檔案等等。我這邊的指令碼都有考慮到

實現程式碼如下:

def getClassNames(filepath):
    #讀取檔名入陣列
    #過濾資料夾
    filterDirs = ["ThirdKit/","小說/"]
    #過濾檔案
    filterFiles = []
    classNames = []
    #遍歷filepath下所有檔案,包括子目錄
    for root, dirs, files in os.walk(filepath):
        for name in files:
            path = os.path.join(root, name)
            #過濾資料夾
            isFilterDir = 0
            for filterDir in filterDirs:
                if filterDir in path:
                    isFilterDir = 1
                    break
            if isFilterDir != 1:
                if ".m" in name:
                    splitNames = name.split(".m")
                    #只選擇.m和.mm結尾的檔案
                    if splitNames[1] == "" or splitNames[1] == "m":
                        cn = splitNames[0]
                        #過濾檔案
                        isFilterFile = 0
                        for ff in filterFiles:
                            if ff == cn:
                                isFilterFile = 1
                        if isFilterFile != 1:
                            #過濾類目
                            if cn.find("+") == -1:
                                print(cn)
                                classNames.append(cn)
    return classNames
複製程式碼

問題二、如何修改檔案中出現的類名並且不出現誤改的情況?

在我搜集到的開源的指令碼中,有極大比例的一部分是直接通過類名替換,其實這特別容易出現誤改。比如我有一個類名為ABC,一個類名為AB,那麼ABC就可能出現被修改兩次的情況。所以我這邊就採用笨辦法,先敲定類名出現的場景,根據其場景設定規則,只有出現類名出現在這些規則中時,才去替換,這樣就可以保證100%的正確率。(這也是大坑,因為不同的程式設計師書寫習慣的問題,導致規則的定義實際極度繁瑣,而且會出現部分遺漏,每一次遺漏後,我都需要新增規則再重跑來驗證··)

下面就是這個指令碼最大的貢獻·· 自認為基本涵蓋完了類名的出現場景(如果有沒有涵蓋的,請記得一定聯絡我!!),一共37種規則,運用這37種規則,做到了一次指令碼,既完美修改,無需在動程式碼就可以直接執行並且不會有閃退問題··

#一開始構思了 14個 後來....
    rule_1 = '"' + cn + '.' #引用修改
    rule_2 = '"' + cn + '"' #類名被直接使用
    rule_3 = ':' + cn + ' ' #繼承 後續有空格
    rule_4 = ':' + cn + '\n' #類名後面是換行
    rule_5 = ' ' + cn + '<'
    rule_6 = ' ' + cn + '\n' #類名後面是換行
    rule_7 = ' ' + cn + ' '
    rule_8 = ' ' + cn + '('
    rule_9 = '[' + cn + ' '
    rule_10 = '[' + cn + '*'
    rule_11 = '(' + cn + '*'
    rule_12 = ')' + cn + '*'
    rule_13 = ' ' + cn + '*'
    rule_14 = ' ' + cn + '\n'
    rule_15 = '(' + cn + ' '
    rule_16 = ' ' + cn + ';'
    rule_17 = ',' + cn + ' '
    rule_18 = ',' + cn + '*'
    rule_19 = ')' + cn + ' ' 
    rule_20 = ',' + cn + ';'
    rule_21 = ' ' + cn + ','
    rule_22 = '<' + cn + '*' #被當做協議 遵守類
    rule_23 = '<' + cn + ' '
    rule_24 = ',' + cn + ','
    rule_25 = ' ' + cn + ':'
    rule_26 = ':' + cn + '//' #後面跟註釋的、、我TM。。
    rule_27 = ' ' + cn + '//' 
    rule_28 = ' ' + cn + '{' #後面跟大括號的··
    rule_29 = ')' + cn + '<' #為什麼遵守協議 也用了 實際類名 沒有用ID
    rule_30 = '(' + cn + '.' #為什麼類要使用.語法
    rule_31 = ' ' + cn + '.'  #類名呼叫.語法
    rule_32 = '!' + cn + '.'  
    rule_33 = ':' + cn + '.'  #類名呼叫點語法 被當做引數傳入
    rule_34 = '[' + cn + '\n' #類名被換行
    rule_35 = ':' + cn + '<' #繼承類名後面 直接接入協議 預設實際是不存在這個問題的
    rule_36 = '"' + cn + '_' #類取名有下劃線以及數字 以及通過工廠用數字來建立的情況
    rule_37 = '"' + cn + '%' #類取名有數字 以及通過工廠用數字來建立的情況
複製程式碼

問題三、如何修改檔名?

這個問題其實很好解決,利用python的os庫就可以直接rename,只是需要拼接全路徑。並且在給類檔案重新命名的時,需要注意字首和字尾新增的位置,不要新增到.h和.m後面去了即可。

問題四、如何同步修改project.pbxproj裡面的檔案資訊?

這裡又和第二個問題一樣需要定義一定規則,才能確保不會出現誤替換,但是這個規則和上面比起來簡直是小巫見大巫。規則如下:

def pbRule(cn):
    rule_1 = '=' + cn + "."
    rule_2 = ' ' + cn + "."
    rule_3 = '/' + cn + "."
    rule_4 = '"' + cn + "."
複製程式碼

以上,問題都解決了。

使用方式

----------指令碼說明----------
指令碼用於批量修改類名
指令碼可傳入四個引數
1、待處理的檔案路徑. example-->'./KanManHua'
2、待修改的pbxproj檔案地址 example--        >'./KanManHua.xcodeproj/project.pbxproj'
3、類名字首 example-->'MHT_'
4、類名字尾 example-->'_MHT'

其中前三個引數為必傳引數 劃重點,要考
----------請開心使用---------
另指令碼支援 -h --help 操作
複製程式碼

當引數錯誤時,也有對應提示以及上述幫助資訊

正常使用

示例:

python changeClassName.py ./KanManHua ./KanManHua.xcodeproj/project.pbxproj MHT_ _MHT
複製程式碼
helpinfo獲取

示例:

python changeClassName.py
python changeClassName.py -h
python changeClassName.py --help
複製程式碼

指令碼地址

後記

由於我司還有需求修改指定 target的類名,實際也有一套可以僅僅只修改target類名的方法,但是由於使用要複雜一點,首先要提取target對應的編譯類,再使用指令碼來修改,修改使用到我之前釋出的一個工具類MacPbxprojHelper,如有需要的話請和我聯絡。 聯絡方式:357863248@qq.com

MacPbxprojHelper介紹連結

相關文章