項(xiàng)目地址
https://github.com/xurunkang/NO_COMPILE
前言
對于 iOS 的中大型項(xiàng)目來說司忱,編譯耗時的問題永遠(yuǎn)是一個痛點(diǎn)。緩解的方案有許多:ccache 等緩存方案 / 優(yōu)化 Xcode 配置 / 加錢堆硬件锄蹂。
這些方案的出發(fā)點(diǎn)都是基礎(chǔ)優(yōu)化編譯耗時來解決的氓仲,哪有沒有一個辦法可以做到不編譯就執(zhí)行修改后的代碼呢?
基于 Objective-C 的動態(tài)特性,是完全可以做到這一點(diǎn)的敬扛,這也是各種熱修復(fù)框架的支撐原理之一晰洒。那么如果需要做到不編譯就執(zhí)行修改后的代碼,我們可以這樣做:獲取本地修改后代碼 -> 轉(zhuǎn) JavaScript 或 Lua -> 模擬器執(zhí)行修改后的腳本啥箭。
大致思路
獲取本地修改代碼
這里也有許多方法谍珊,可以手動復(fù)制,也可以自動獲取急侥。這里我是選擇利用 Xcode Editor Extension 來獲取到你選中的修改代碼的砌滞。
Objective-C 轉(zhuǎn) JavaScript
由于整個流程我是基于 JSPatch 來開發(fā)的,所以是需要轉(zhuǎn)為 JS 的腳本坏怪。這里我是寫了個 node.js 的腳本來實(shí)現(xiàn)贝润,轉(zhuǎn)換算法是利用 https://github.com/bang590/JSPatchConvertor 中的開源代碼。
模擬器執(zhí)行修改后的腳本
由于已經(jīng)有 JSPatch 完整的框架做支撐铝宵,這里只需要利用其中的方法 -[JPEngine evaluateScriptWithPath:] 去執(zhí)行修改后的腳本即可打掘。
具體實(shí)現(xiàn)流程圖
- 項(xiàng)目和本地 Node 服務(wù)器建立 Socket 連接
- 修改 test 代碼
- 利用 Xcode Editor Extension 獲取修改的代碼
- 將修改代碼發(fā)送到本地 Node 服務(wù)器
- 執(zhí)行 Node 腳本將 OC 轉(zhuǎn) JS
- 執(zhí)行 Node 腳本將 JS 寫入到本地文件
- 利用 Socket 通知項(xiàng)目更新
- 項(xiàng)目執(zhí)行 -[JPEngine evaluateScriptWithPath:] 函數(shù)注入 JS 代碼
- 重新執(zhí)行 test 代碼
(我是從零開始的啊,為什么markdown就要轉(zhuǎn)為1呢~)
這里使用 Node.js 有兩個原因:Xcode Editor Extension 不支持直接執(zhí)行沙盒外腳本(所以是通過 Extension 向 Node 服務(wù)器發(fā)送 Http 請求來傳遞修改的代碼),而且和 iOS 模擬器進(jìn)行進(jìn)程通信比較麻煩(嘗試了 CFNotification 等幾種方法都不行鹏秋,所以使用 Node 搭建 Socket 服務(wù)器達(dá)到進(jìn)程通信)尊蚁。
視頻演示
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