熱更新JSPatch學習:

熱更新的基礎理論和需求原因就不介紹了,不清楚的可以百度,APP線上修復bug類似於遊戲的補丁修復,這裏給出幾個可行的技術方案並比較其優缺點


一:實現熱更新的幾種思路:


1,原生動態化
在保持原生語言開發的基礎上加入動態補丁修復,保證APP性能和效果的同時完成bug修復和模塊添加,目前使用較多的有兩種方式,一是廣泛應用的JSPatch,該方案可以實時修復線上bug,安全快速,官網sdk使用RSA簽名加密,本地存儲加密保證腳本安全,需要接sdk。二是私有方案,目前滴滴和手Q等自研的dynamicCocoa可以實現熱更新,功能強大,不過未開源


2.優化web性能入手
weex是阿里前端技術團隊開源的項目,用於APP上可以實現web方式開發,原生方式渲染,擁有web開發和發佈的優勢,又有不錯的性能體驗,缺點是接入成本高,學習成本和維護成本高,團隊學習成本比較高。二是React-Native,RN技術近來火熱。可以單獨開發APP,爲APP動態添加模塊,有自己的IDE支持,開發效率高,目前能替代就是本來採用H5開發的模塊,不是原生語言開發,流暢度和視覺效果可能差一點


3.動態庫(已經被蘋果屏蔽)
waxPatch,可以用lua調用OC方法,但是蘋果有規定iOS Developer Program License Agreement裏3.3.2提到不可動態下發可執行代碼,而waxPatch屬於這種,並且開發團隊已經停止開發維護,不支持OC裏的block和lua程序互傳


綜上所述,集合目前主流開發語言和趨勢,可以使用原生動態化方案裏的JSPatch方案,和優化web性能的RN方案。我沒學過RN 所以只分析JSPatch


使用方法是bang神開發的JSPatch,這裏附上鍊接:http://blog.cnbang.net/works/2767/


主要使用JS的API:defineClass(classDeclaration,[property,], instanceMethods, classMethod), 其中,第一個參數classDeclaration:字符串,類名/父類名和protocol,第二個參數,新增的屬性property,字符串數組(可省略),第三個參數,instanceMethods:要添加或覆蓋的實例方法,第四個參數classMethods:要添加或覆蓋的類方法


覆蓋方法
1.在define class裏定義已存在的方法即可覆蓋,方法名規則與調用規則一樣,使用_分隔
比如在項目內有一個方法出錯,需要線上修復
@implementation  FoundVIewController內
- (void) tableview:(uitableview *)tableview didselectRowAtIndexPath:(nsindexPath *)indexPath{
@throw [NSException exceptionWithName:@“點擊就出錯了”  reson:@“就不讓你瞎點,點了就崩” userinfo:nil];
}

@end
在上述代碼中,tabbar的發現部分是一個表格,點擊所有的表格都會造成崩潰,是一個bug,那麼如何修復呢?可以使用方法覆蓋
defineClass(“FoundViewController”, {
tableview_didselectRowAtIndexpath: function(tableview,indexPath) {
consoleLog(“替換了這個就不讓你怎麼點都不會崩潰”);
}
});
如果OC方法名中有下劃線,那麼在js使用的時候就要用雙下劃線來替代
// OC
@implementation JPTableViewController
- (NSArray *) _dataSource {
}
@end
// JS
defineClass("JPTableViewController", {
  __dataSource: function() {
  },
})
現在有這樣一種情況:
如果一個bug其實是後臺的原因造成,但是他們修復起來有一定的開發量和時間,那麼我幫他們上了一個js來熱更新一下暫時改我的代碼邏輯,當後臺完成修復後  我需要讓我的新加的js方法失效,還用成原來的方法,該怎麼做呢?
在我熱更新的js文件添加如下邏輯就可以了。正常使用時還需要添加一個條件判斷等

// OC
@implementation JPTableViewController
- (void)viewDidLoad {
}
@end
// JS
defineClass("JPTableViewController", {
  viewDidLoad: function() {
     self.ORIGviewDidLoad();
  },
})
現在有這樣一種情況,後臺給我返回字符串類型的數據,我定義的字符串的屬性修飾符沒有用copy,而是用了strong,結果使用的時候發現數據不對,我要修改這麼一個屬性修飾符。
// OC
@interface JPTableViewController
@property (nonatomic) NSArray *data;
@property (nonatomic) NSString *shareURL;
@property (nonatomic) NSString *shareTitle;
@end
@implementation JPTableViewController
@end
// JS
defineClass("JPTableViewController", {
  viewDidLoad: function() {
     var data = self.data();     //get property value
     self.setData(data.toJS().push("JSPatch"));     //set property value
     var sel = self;
     self.bridge().registerHandler_handler('h5ToNativeShareDialog', block('NSDictionary *',function(data,responseCallback) {         
         sel.setShareURL(data.objectForKey('url'));
         sel.setShareTitle(data.objectForKey('title'));
     }));
})
動態新增property
可以在 defineClass() 第二個參數爲類新增 property,格式爲字符串數組,使用時與 OC property 接口一致:
defineClass("JPTableViewController", ['data', 'totalCount'], {
  init: function() {
     self = self.super().init()
     self.setData(["a", "b"])     //添加新的 Property (id data)
     self.setTotalCount(2)
     return self
  },
  viewDidLoad: function() {
     var data = self.data()     //獲取 Property 值
     var totalCount = self.totalCount()
  },
})

現在有這樣的一個簡單的需求,代碼裏的方法沒有錯,只是由於之前沒想好,少了一些邏輯和對數據的處理,重新發版又犯不上,那怎麼辦呢?可以利用JSPatch來爲類中任意添加方法的功能來實現這個需求。
示例方法:
// OC
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 
// 巴拉巴拉你自己的邏輯
}


現在要在裏面加一些各種邏輯判斷數據處理,放在一個方法裏,名字叫做addNewMethod,然後把這個方法放在每次點擊的時候觸發。那麼我在js中可以這麼寫
// JS
defineClass("FoundViewContrller",
tableview_didselectRowAtIndexPath: function(tableview, indexpath){
// 巴拉巴拉你自己的邏輯
self.addNewMethod();// 指你要添加的方法名字,在oc中的didSelectRowAtIndexPath方法要調用
addNewMethod: function(){// 方法內部
// 新添加的邏輯和處理。
}
}
)
這樣就可以了。



一:
有C的語法部分,如NSLog
NSLog  使用console.log("呵呵呵 全給替代了”);這種
有block部分,有gcd的部分,具體可以查看上面我附的連接,查看原作者的文檔介紹可以看的更詳細。大多數時候我們熱修復只是針對一定的bug修復,如果要是添加模塊增加功能,還是建議上版本



本人創建了一個公衆號,裏面每天發一些教程進階知識,有的是本人總結所得,有的是轉載大神的文章,大家一起分享看。掃碼關注公衆號:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章