純粹是技術分享,歡迎到github點贊。
https://github.com/dKingbin/DynamicOC
複製代碼
iOS熱修復方案通過JSPatch事件後,也消停了好久。bang神在《JSPatch – 動態更新iOS APP》中曾提到,爲了更符合Apple的規則,即《Apple Developer Program License Agreement》 裏3.3.2提到的不可動態下發可執行代碼。 JSPatch特意繞了js的圈子,從而實現曲線救國、實現熱更新的方案。可是事實證實了Apple對於這種方案也是不承認的,根本的緣由仍是在於JSPath作得太過極致--支持絕大部分的OC/C語法。javascript
既然JSPatch繞道js的方法,已經被Apple拒絕了,那麼就再次回到原點,從新出發。新的框架或者新的方案我以爲至少有一個充分條件,就是不能太極致。 Objective-C做爲一種動態的語言,所以可以動態執行全部OC語法是正常的,Aspects相似的框架也是被Apple承認的。至因而否須要運行全部的C函數,這個有待商榷。 第二個方面,則是放棄javascript/lua等相似語言做爲更新的腳本,而是採用原生的Objective-C做爲更新的腳本語言。java
C語言是沒有反射機制的,做爲一門編譯型語言,在編譯期間就已經生成機器碼。所以若是要從字符串中獲取到對應的函數指針,那麼大概有兩種方法:git
第二種是目前JSPatch採用的辦法,固然也被Apple警告了。dlsym功能很是強悍,是獲取函數指針的最優解。 第一種侷限性很是大,可是沒有用到黑魔法。github
經過flex/yacc,直接解析Objective-C語法,再也不採起js/lua等腳本語言。objective-c
通過上面的思考,在最近業餘中作了DynamicOC的項目,百分百原生支持採用Objective-C做爲更新的腳本語言。 固然動態運行C函數仍是採用dlsym獲取函數指針的辦法,後面會逐步改成映射表的作法。bash
DynamicOC使用flex/yacc進行詞法解析和語法分析,轉爲一顆語法生成樹AST。 而後經過解析每一個節點,從而執行相應的代碼。由於採用的是Objective-C做爲腳本語言,所以極容易適配。框架
NSString* text = @" \ __block int result = 0;\ UIView* view = [[UIView alloc]init];\ void(^blk)(int value) = ^(int value){\ view.tag = value;\ };\ blk(1024);\ return view.tag;";
ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);
複製代碼
int echo(int value) {
return value;
}
NSString* text = @" \ [OCCfuntionHelper defineCFunction:@\"echo\" types:@\"int, int\"]; \ return echo(1024);";
ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);
複製代碼
NSString* text = @" \ [OCCfuntionHelper defineCFunction:@\"objc_setAssociatedObject\" types:@\"void,id,void *,id,unsigned int\"];\ [OCCfuntionHelper defineCFunction:@\"objc_getAssociatedObject\" types:@\"id,id,void *\"];\ NSString* key = @\"key\"; \ objc_setAssociatedObject(self, key, @(1024), 1);\ return objc_getAssociatedObject(self, key);";
ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);
複製代碼
Github連接在此: DynmaicOC, 以爲有幫助的能夠點個星哦!謝謝!異步