javascript
JSPatch – 动态更新iOS APP
JSPatch是最近業余做的小項目,只需在項目中引入極小的引擎,就可以使用JavaScript調用任何Objective-C的原生接口,獲得腳本語言的能力:動態更新APP,替換項目原生代碼修復bug。?
用途?
是否有過這樣的經歷:新版本上線后發現有個嚴重的bug,可能會導致crash率激增,可能會使網絡請求無法發出,這時能做的只是趕緊修復bug然后提交等待漫長的AppStore審核,再盼望用戶快點升級,付出巨大的人力和時間成本,才能完成此次bug的修復。?
使用JSPatch可以解決這樣的問題,只需在項目中引入JSPatch,就可以在發現bug時下發JS腳本補丁,替換原生方法,無需更新APP即時修復bug。?
例子?
@implementation JPTableViewController ... - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {NSString *content = self.dataSource[[indexPath row]]; //可能會超出數組范圍導致crashJPViewController *ctrl = [[JPViewController alloc] initWithContent:content];[self.navigationController pushViewController:ctrl]; } ... @end上述代碼中取數組元素處可能會超出數組范圍導致crash。如果在項目里引用了JSPatch,就可以下發JS腳本修復這個bug:?
#import “JPEngine.m" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {[JPEngine startEngine];[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cnbang.net/bugfix.JS"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];if (script) {[JPEngine evaluateScript:script];} }];….return YES; } @end //JS defineClass("JPTableViewController", {//instance method definitionstableView_didSelectRowAtIndexPath: function(tableView, indexPath) {var row = indexPath.row()if (self.dataSource().length > row) { //加上判斷越界的邏輯var content = self.dataArr()[row];var ctrl = JPViewController.alloc().initWithContent(content);self.navigationController().pushViewController(ctrl);}} }, {})這樣 JPTableViewController 里的 -tableView:didSelectRowAtIndexPath: 就替換成了這個JS腳本里的實現,在用戶無感知的情況下修復了這個bug。?
更多的使用文檔和demo請參考github項目主頁。?
原理?
JSPatch用iOS內置的JavaScriptCore.framework作為JS引擎,但沒有用它JSExport的特性進行JS-OC函數互調,而是通過Objective-C Runtime,從JS傳遞要調用的類名函數名到Objective-C,再使用NSInvocation動態調用對應的OC方法。詳細的實現原理以及實現過程中遇到的各種坑和hack方法會另有文章介紹。?
方案對比?
目前已經有一些方案可以實現動態打補丁,例如WaxPatch,可以用Lua調用OC方法,相對于WaxPatch,JSPatch的優勢是:?
1.JS語言
JS比Lua在應用開發領域有更廣泛的應用,目前前端開發和終端開發有融合的趨勢,作為擴展的腳本語言,JS是不二之選。?
2.符合Apple規則
JSPatch更符合Apple的規則。iOS Developer Program License Agreement里3.3.2提到不可動態下發可執行代碼,但通過蘋果JavaScriptCore.framework或WebKit執行的代碼除外,JS正是通過JavaScriptCore.framework執行的。?
3.小巧
使用系統內置的JavaScriptCore.framework,無需內嵌腳本引擎,體積小巧。?
4.支持block
wax在幾年前就停止了開發和維護,不支持Objective-C里block跟Lua程序的互傳,雖然一些第三方已經實現block,但使用時參數上也有比較多的限制。?
相對于WaxPatch,JSPatch劣勢在于不支持iOS6,因為需要引入JavaScriptCore.framework。另外目前內存的使用上會高于wax,持續改進中。?
風險?
JSPatch讓腳本語言獲得調用所有原生OC方法的能力,不像web前端把能力局限在瀏覽器,使用上會有一些安全風險:?
1.若在網絡傳輸過程中下發明文JS,可能會被中間人篡改JS腳本,執行任意方法,盜取APP里的相關信息??梢詫鬏斶^程進行加密,或用直接使用https解決。?
2.若下載完后的JS保存在本地沒有加密,在未越獄的機器上用戶也可以手動替換或篡改腳本。這點危害沒有第一點大,因為操作者是手機擁有者,不存在APP內相關信息被盜用的風險。若要避免用戶修改代碼影響APP運行,可以選擇簡單的加密存儲。?
其他用途?
JSPatch可以動態打補丁,自由修改APP里的代碼,理論上還可以完全用JSPatch實現一個業務模塊,甚至整個APP,跟wax一樣,但不推薦這么做,因為:?
若想動態為APP添加模塊,目前React Native給出了很好的方案,解決了上述三個問題:?
所以動態添加業務模塊目前還是推薦嘗試React Native,但React Native并不會提供原生OC接口的反射調用和方法替換,無法做到修改原生代碼,JSPatch以小巧的引擎補足這個缺口,配合React Native用統一的JS語言讓一個原生APP時刻處于可擴展可修改的狀態。?
—?
目前JSPatch處于開發階段,穩定性和功能還存在一些問題,歡迎大家提建議/bug/PR,一起來做這個項目。
github地址:?https://github.com/LazyDuan/JSPatch
來自:http://blog.cnbang.net/works/2767
轉載于:https://www.cnblogs.com/LazyDuan/p/4968887.html
總結
以上是生活随笔為你收集整理的JSPatch – 动态更新iOS APP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (软件工程复习核心重点)第四章总体设计-
- 下一篇: (软件工程复习核心重点)第八章面向对象方