前言
近日由於種種原因,需要把程式碼裡面的類全部都修改一遍類名。
在網上找了一圈相關的開源庫,沒有發現有合適滿意的,始終都存在一些問題,要麼出現誤修改,要麼把方法名或者屬性名也給修改了等等情況。
於是決定掏出生疏的Python來寫一個。
批量修改類名需要解決四個問題:
-
- 如何取得需要修改的類名?
-
- 如何修改檔案中出現的類名並且不會出現誤改等情況?
-
- 如何修改檔名?
-
- 修改檔名後,如何同步修改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