更新完畢
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ū)】

這些大廠都在用著一套可以實現(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上下載源碼,加入到工程中

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

首先在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