纯粹是技术分享,欢迎到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, 以为有帮助的能够点个星哦!谢谢!异步