一鍵清除 objc 專案中的無用方法

發表於2016-10-30

當專案越來越大,引入第三方庫越來越多,上架的APP體積也會越來越大,對於使用者來說體驗必定是不好的。在清理資源,編譯選項優化,清理無用類等完成後,能夠做而且效果會比較明顯的就只有清理無用函式了。現有一種方案是根據Linkmap檔案取到objc的所有類方法和例項方法。再用工具逆向可執行檔案裡引用到的方法名,求個差集列出無用方法。這個方案有些比較麻煩的地方,因為檢索出的無用方法沒法確定能夠直接刪除,還需要挨個檢索人工判斷是否可以刪除,這樣每次要清理時都需要這樣人工排查一遍是非常耗時耗力的。

這樣就只有模擬編譯過程對程式碼進行深入分析才能夠找出確定能夠刪除的方法。具體效果可以先試試看,程式程式碼在:https://github.com/ming1016/SMCheckProject 選擇工程目錄後程式就開始檢索無用方法然後將其註釋掉。

首先遍歷目錄下所有的檔案。

然後將註釋排除在分析之外,這樣做能夠有效避免無用的解析。這裡可以這樣處理。

這裡//這種註釋是允許換行的,所以使用.*的方式會有問題,因為.是指非空和換行的字元。那麼就需要用到[\s\S]這樣的方法來包含所有字元,\s是匹配任意的空白符,\S是匹配任意不是空白符的字元,這樣的或組合就能夠包含全部字元。

接下來就要開始根據標記符號來進行切割分組了,使用Scanner,具體方式如下

由於objc語法中有行分割解析的,所以還要寫個行解析的方法

獲得這些資料後就可以開始檢索定義的方法了。我寫了一個類專門用來獲得所有定義的方法

這個方法大概的思路就是根據標記符設定不同的狀態,然後將獲取的資訊放入定義的結構中,這個結構我是按照檔案作為主體的,檔案中定義那些定義方法的列表,然後定義一個方法的結構體,這個結構體裡定義一些方法的資訊。具體結構如下

有了檔案裡定義的方法,接下來就是需要找出所有使用過的方法,這樣才能夠通過差集得到沒有用過的方法。獲取使用過的方法,我使用了一種時間複雜度較優的方法,關鍵在於對方法中使用方法的情況做了計數的處理,這樣能夠最大的減少遍歷,達到一次遍歷獲取所有方法。具體實現如下

比對後獲得無用方法後就要開始註釋掉他們了。這裡用的是逐行分析,使用解析定義方法的方式通過方法結構體裡定義的唯一識別符號來比對是否到了無用的方法那,然後開始新增註釋將其註釋掉。實現的方法具體如下:

完整程式碼在:https://github.com/ming1016/SMCheckProject 這裡。基於語法層面的分析是比較有想象的,後面完善這個解析,比如說分析各個檔案import的標頭檔案遞迴來判斷哪些類沒有使用,通過獲取的方法結合獲取類裡面定義的區域性變數和全域性變數來分析迴圈引用,通過獲取的類的完整結構還能夠將其轉成JavaScriptCore能解析的js語法檔案。

相關文章