【進(jìn)階篇】iOS解決方案JSPatch

更新完畢

iOS App審核是所有iOS開發(fā)者心中的一座山,漫長的等待時間如果在正常的版本更新時還好,但是在線上出現(xiàn)嚴(yán)重BUG時,沒一分每一秒對我們來說都是一種煎熬,面對這樣的問題,難道騰訊,阿里都跟我們一樣嗎?
<h5>當(dāng)然不是</h5>
看看他們的解決方案:

1、微信為代表的JSPatch:https://github.com/bang590/JSPatch
2、阿里為代表的Wax:https://github.com/alibaba/wax



好幾次App剛剛審核通過,卻發(fā)現(xiàn)其中有致命的BUG,修改的話可能就是一兩行代碼就能搞定,但是蘋果的審核時間讓你起碼幾天面對這個BUG提心吊膽,對于飽受這份折磨的我來說,JSPatch簡直就是救世主,話不多說,看都有誰在用這個:圖片源自http://using.jspatch.org/ 【JSPatch使用統(tǒng)計社區(qū)】

image


這些大廠都在用著一套可以實現(xiàn)hit code push的解決方案
讓我們來認(rèn)識一下JSPatch吧,原作者博客地址:

<h3>http://blog.cnbang.net/</h3>


<h4>JSPatch原理</h4>
JSPatch的基本原理就是通過JS代碼,利用OC運行時的特性,已達(dá)到修改程序代碼,讓App具備<span style='font-size:25px'>hit code push</span>的能力,更詳細(xì)的原理可以去看上面原作者的博客,里面非常詳細(xì)的講解了JSPatch的底層實現(xiàn)。
JS文件通過從服務(wù)器下載到本地,所有使用時需要服務(wù)器的一定配合。


<h4>JSPatch的兩個安全問題</h4>
1、傳輸安全:JS 腳本可以調(diào)用任意 OC 方法,權(quán)限非常大,若被中間人攻擊替換代碼,會造成較大的危害。
2、執(zhí)行安全:下發(fā)的 JS 腳本靈活度大,相當(dāng)于一次小型更新,若未進(jìn)行充分測試,可能會出現(xiàn) crash 等情況對 APP 穩(wěn)定性造成影響。
<h6>所以,使用時對js文件的內(nèi)容進(jìn)行加密是必須的</h6>


<h4>JSPatch的使用</h4>
先去GitHub上下載源碼,加入到工程中


image

JSPatch經(jīng)過作者的多次優(yōu)化,在不斷完善的過程中還是保持了極小的代碼量,只有一千多行 OC 和接近兩百行 JS(PS:再次膜拜一下大神)
這里使用到了JavaScriptcore核心庫,所以還需要在General的Linded Framework and Libraries添加JavaScriptcore.framework


image

首先在AppDelegate中添加<code>JPEngine.h</code>的頭文件
然后添加下面兩個方法:

<pre><code class='hljs'>
// Library/Caches

define FilePath ([[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil])

/**

  • 下載JSPatch
    */
    -(void)loadJSPatch
    {
    //使用AFNetWork下載在服務(wù)器的js文件
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    NSURL *URL = [NSURL URLWithString:@"http://blog.methodname.com/content/test.js"];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
    {
    NSURL *documentsDirectoryURL = FilePath;
    //保存到本地 Library/Caches目錄下
    return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
    }
    completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
    {
    NSLog(@"File downloaded to: %@", filePath);
    }];
    [downloadTask resume];

}

/**

  • 運行下載的JS文件
    */
    -(void)HSDevaluateScript
    {

    //從本地獲取下載的JS文件
    NSURL *p = FilePath;
    //獲取內(nèi)容
    NSString *js = [NSString stringWithContentsOfFile:[p.path stringByAppendingString:@"/test.js"] encoding:NSUTF8StringEncoding error:nil];

    //如果有內(nèi)容
    if (js.length > 0)
    {
    //-------
    //在此處解密js內(nèi)容
    //----

    //運行
    [JPEngine startEngine];
    [JPEngine evaluateScript:js];
}

}
//還是在AppDelegate中下面的兩個方法內(nèi),進(jìn)行下載服務(wù)器的js文件和運行下載后的js文件
//加載配置

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    //可以在這里設(shè)置一個條件,比如隔多久才去請求一次服務(wù)器看看有沒有可以下載的文件
    //以防止頻繁請求
    [self loadJSPatch];

    return YES;
    }
    //應(yīng)用程序進(jìn)入活動狀態(tài)時

  • (void)applicationDidBecomeActive:(UIApplication *)application
    {
    [self HSDevaluateScript];
    }
    </code></pre>

以上在客戶端的配置就完成了

然后就是最關(guān)鍵的,如何使用js來完成調(diào)用,替換,覆蓋原來的代碼

JSPatch OC-JS自動轉(zhuǎn)換工具:https://github.com/bang590/JSPatchConvertor

如果不想去記它的語法,完全可以用這個工具來進(jìn)行OC,JS的轉(zhuǎn)換,工具也是原作者寫的(PS:再次膜拜大神,雖然有些語法上的瑕疵,具體請看github上的wiki)
<pre>
<code class='hljs'>

//在MainViewController的viewDidLoad方法中將self.view的背景顏色改為橙色
//-------OC代碼
@implementation MainViewController
-(void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor orangeColor]];
}
//------轉(zhuǎn)換后的JS代碼

require('UIColor,UIViewController');//這里少了個UIViewController加上就好
defineClass('MainViewController', {
viewDidLoad: function() {
super.viewDidLoad();
self.view().setBackgroundColor(UIColor.orangeColor());
},
});
</code></pre>



將這個文件,放在服務(wù)器上面,最好進(jìn)行版本分類,這樣在App下載的時候,就能根據(jù)當(dāng)前的版本號來進(jìn)行對應(yīng)目錄下的文件的下載例如:

AppName-->2.1-->jspatch.js
AppName-->2.2-->jspatch.js
AppName-->2.3-->jspatch.js

這樣就能在App上根據(jù)目錄:AppName(當(dāng)前App版本號)\jspatch.js 這樣的方式去下載對應(yīng)版本的js文件了


注意事項:

引用某位使用過JSPatch大神博客里最后的話 http://www.cnblogs.com/dsxniubility/p/5080875.html

1、接入了JSPatch之后,iOS的線上BUG 看上去就不向以前那樣“猛如虎”了,但是這僅僅是一個緊急預(yù)案措施,以前規(guī)范的流程還是需要遵守。

2、每一次本版本用JSPatch解決的線上Bug,下個版本必須用OC代碼寫入項目中,不能允許補丁代碼的存留超過一個版本。

3、倡導(dǎo)使用敏捷開發(fā)的思想,類似于主邏輯或者是功能模塊入口的方法可以抽的更細(xì),這樣即使需要修改,成本也不會太大,作者本人也提到,如果有一行代碼必須要在一個大方法的中間進(jìn)行修改,那我也沒辦法了,你只能把這整個方法都用js寫一遍了,所以才設(shè)置了JSPatchConvertor。

4、每次用JSPatch解決掉的線上BUG 應(yīng)當(dāng)有一個專門的文檔記錄,遇到重復(fù)錯誤必須寫casestudy。

5、具體的使用請查看github上的wiki JSPatch wiki

最后:<code>放上JSPatch的官網(wǎng)</code>



目前jspatch的作者已經(jīng)將jspatch商業(yè)化,并提供了完善的版本控制,腳本下發(fā)SDK,集成到APP中也只需要一行代碼。
JSPatch


END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容