iOS 遠端代碼下發,有什麼設想思緒 ?
平常人人都用 JSPatch?
用他人的,總不好。老王造了個輪子,我來形貌一下。
老王 Patch, 挺先進的。JavaScript 代碼, 採納 WebPack 打包。也參考了 JSPatch ,
怎樣設想這個 Patch?
從原理上
Patch 主如果 干什麼的呢?
平常大公司的 App 在運轉的歷程當中,營業線異常複雜,能夠會湧現一些問題。
這個時刻,打補丁比較好
可以遠端下發一個文件,拓荒的 App 經由過程 加載 這個文件,
實行 這個 代碼 補丁。
這個模樣,就可以經由過程遠端, 把這個代碼, 在拓荒的 app 運轉當中,給實行過來,
OC 可以的,由於是動態言語,有 runtime ,所以才搞這個 patch。
OC 有自身的音訊轉發流程。 Runtime 有 objc_msgSend
和 _objc_msgForward
。
Runtime 有這兩個要領,
這兩個函數特徵,讓一切的函數挪用都邑走這兩個要領。
如許就可以干一些 patch 的事變。
別的一點, 在 App 中植入了這個 patch ,他所應用的言語,可以被 eval 。
eval, 推斷代碼語句可以實行
如許 app 中有一個 context, 可以實行用於 patch 的言語。
本文中的 iOS 補丁計劃直接應用 這個 JavaScriptCore,
就是應用 JavaScriptCore 供應的 JSContext.
能讓 JavaScript 言語 和 Objective-C 之間,有一個接口。然後就可以 JavaScript 與 Objective-C 互相挪用了。
( 蘋果自身完成的 )
JSPatch 用到了 FFI,這個庫老王 Patch 也應用了 FFI .
FFI, Foreign Function Interface ,就是把一個言語暴露出來的接口,能讓其他言語來挪用。
Java 的 JNI 規範,與 FFI 比較相似。
FFI ,起首順從 Coding Convention ,就是定義恪守一些挪用的協媾和劃定。
為何要有 FFI 呢?
舉個 🌰:
我們實行一個函數挪用,起首拓荒一個棧幀,這個棧幀通報一些什麼樣的參數?參數的範例是什麼?參數 的個數,是多少?包含這個函數內里,實行的一些行動是什麼?
FFI 就把恪守的一些挪用的協媾和劃定定義出來。
老王 Patch 庫的這個自定義 FFI , 就是把想做的 patch 言語, 對接 Objective-C 的實行環境。
須要往內里通報的敕令,把這個東西,給劃定出來。
這個模樣, 在實行這個 Patch 的歷程當中,就可以根據這個敕令,去發響應的音訊,讓響應的 context ,實行須要 patch 的代碼。
FFI 就到這裏了。 開啟預編譯。
應用 JSPatch 的歷程當中,老王發明,用的異常的不順手,
為何他不順手呢?
老王認為,JSPatch 把 JavaScript 硬生轉換成相當於 Objective-C 這類作風的,補丁代碼。
其間,還做了許多的言語處置懲罰,包含 Bang 說的源函數的處置懲罰。
包含 C 言語函數,相似 Ruby 的 Method Mission .
至於其他, 老王認為, JSPatch 都是在後端舉行的。
JavaScript 的 逼真度
要加強Patch, 自身具有的言語的一個膩滑性,就是寫 JavaScript , 就應用 JavaScript 的寫法
引出了預編譯的歷程:
把 JavaScriptContext 的註冊接口,籠統出三個層,
define, 定義
define, 往 Objective-C 發音訊。 不須要參數返回, 可以用 define .
須要定義的,肯建都自身定義的。
籠統出這一層,就可以了。
evaluate
須要一個返回值的時刻,應用
去實行一些什麼使命
Callback
老王覺得蘋果封裝的 JavaScriptContext,能夠有一些問題。
比如說, 通報的一些函數對象,拓荒者封裝了兩層。那就能夠獵取不到這個對象了。
這個時刻, 須要 Callback 體式格局,在誰人實行環境當中,獵取前端的 function 內容。
用 JavaScriptCore 相干的一種回調體式格局,來取到在當前 JavaScriptContext 環境 當中的一個 function 值。
另有就是指令範例
這個 patch ,是干什麼的? 對所應用的內容, 有哪些指令?
- Patch 就是 實行 一些 Method 函數 的 一些 hook,
- 會修正 一些 property 的值了。
- 會 做一些 block 方面的改動了。
- 接見 父類 super
- 我們 可以 新增 函數,method_create
經由過程 這些指令,我們可以完成, 想要 patch 到的一些功用
另有關鍵字轉換:這個經由過程預處置懲罰來完成。要完成對一些關鍵字的處置懲罰。
關於 Objective-C 中的 self 關鍵字, 一般用來代表當前對象的指針。
還須要改 super 關鍵字, 為 oc_super. 由於 super 在 ECMAScript 6 內里, 也是關鍵字了,須要逃避掉。
original, 是 Patch 中特有的。挪用之前的函數,即打補丁之前的這個函數的挪用。
一些優化,舉個 🌰: JS 寫 高階函數
對 JavaScript 高階函數做一個膩滑處置懲罰,不然能夠寫起來,異常費力。
a.request(
function(a:id,b:Int):double{},
callback:(string,string) => int,
(num1:string, num2:double) => { return num1 + num2; }
);
request 要領, 有三個參數。三個 function 範例的參數。第一個 function 函數,吸收兩個參數。第二個參數 callback, 是我們在函數挪用高低文中取到的。第三個參數是, ECMAScript 6 中應用的箭頭函數。
最好呢,對這個舉行一些支撐。
這些操縱,是經由過程預處置懲罰的體式格局,
編譯成,可以對接 OC 的 Block 指令的。
然後,才 一般 完成事情。
JSPatch 是很好的參考,
人人都模仿 JSPatch,在 JavaScriptContext 中註冊一大堆自身要舉行 patch 的函數。
想要用到什麼,就去補充什麼。
平常都是完整自創 Bang 的一些主意。
最好呢? 要把 JSPatch 的這麼一些主意,背地的東西,給籠統出來。
瑕玷,沒應用挺好用的 JSExport 協定, JSVirtualMachine
Github 官方 repo 鏈接:https://github.com/wangyunico…
我的民間 repo , https://github.com/BoxDengJZ/…