項目地址
https://github.com/xurunkang/NO_COMPILE
前言
對于 iOS 的中大型項目來說,編譯耗時的問題永遠是一個痛點。緩解的方案有許多:ccache 等緩存方案 / 優(yōu)化 Xcode 配置 / 加錢堆硬件。
這些方案的出發(fā)點都是基礎(chǔ)優(yōu)化編譯耗時來解決的,哪有沒有一個辦法可以做到不編譯就執(zhí)行修改后的代碼呢?
基于 Objective-C 的動態(tài)特性,是完全可以做到這一點的,這也是各種熱修復框架的支撐原理之一。那么如果需要做到不編譯就執(zhí)行修改后的代碼,我們可以這樣做:獲取本地修改后代碼 -> 轉(zhuǎn) JavaScript 或 Lua -> 模擬器執(zhí)行修改后的腳本。
大致思路
獲取本地修改代碼
這里也有許多方法,可以手動復制,也可以自動獲取。這里我是選擇利用 Xcode Editor Extension 來獲取到你選中的修改代碼的。
Objective-C 轉(zhuǎn) JavaScript
由于整個流程我是基于 JSPatch 來開發(fā)的,所以是需要轉(zhuǎn)為 JS 的腳本。這里我是寫了個 node.js 的腳本來實現(xiàn),轉(zhuǎn)換算法是利用 https://github.com/bang590/JSPatchConvertor 中的開源代碼。
模擬器執(zhí)行修改后的腳本
由于已經(jīng)有 JSPatch 完整的框架做支撐,這里只需要利用其中的方法 -[JPEngine evaluateScriptWithPath:] 去執(zhí)行修改后的腳本即可。
具體實現(xiàn)流程圖

- 項目和本地 Node 服務器建立 Socket 連接
- 修改 test 代碼
- 利用 Xcode Editor Extension 獲取修改的代碼
- 將修改代碼發(fā)送到本地 Node 服務器
- 執(zhí)行 Node 腳本將 OC 轉(zhuǎn) JS
- 執(zhí)行 Node 腳本將 JS 寫入到本地文件
- 利用 Socket 通知項目更新
- 項目執(zhí)行 -[JPEngine evaluateScriptWithPath:] 函數(shù)注入 JS 代碼
- 重新執(zhí)行 test 代碼
(我是從零開始的啊,為什么markdown就要轉(zhuǎn)為1呢~)
這里使用 Node.js 有兩個原因:Xcode Editor Extension 不支持直接執(zhí)行沙盒外腳本(所以是通過 Extension 向 Node 服務器發(fā)送 Http 請求來傳遞修改的代碼),而且和 iOS 模擬器進行進程通信比較麻煩(嘗試了 CFNotification 等幾種方法都不行,所以使用 Node 搭建 Socket 服務器達到進程通信)。
視頻演示
http://ocnnxadky.bkt.clouddn.com/KK_NO_COMPILE_DEMO.mp4
缺陷
自動轉(zhuǎn)換腳本目前不支持如下類型:
Macro / constant variable / Enum
C function calling
GCD functions
Pointer / Struct
Getting / Setting private variable