最近在做动态化方案看了很多相关的项目,rn、weex、luaview、lua+wax、jspatch等等,打算把其中核心的方案记录下来。
JSPatch的原理有很详细的讲解。跟lua+wax的核心原理基本一致,都是利用oc的运行时动态消息机制,但js不支持消息转发,作者很巧妙的替换了所有方法名让所有调用都走到同一个方法来处理再交给oc进行消息处理。
js脚本修改
如上面所说,js无法直接调用oc方法,会因为找不到方法而报错,于是对js脚本进行修改让其不报错又能运行。对js内所有的方法进行正则匹配,把方法名替换为__c,原方法名变为字符串类型的参数。通过__c()方法实现对oc的调用。
js对oc方法调用,即__c()的实现
- 获取参数,也就是原js的方法名,如果当前js对象有这个字段就直接执行。
- 取得类或对象和方法名,返回一个匿名函数。
- js在__c("methodName")没有修改,所以会紧跟对oc方法调用的参数。这个匿名函数调用时可以直接取到所有参数。
- 有了方法和参数,再对方法名作进一步修改,因为在js里调用oc方法时的方法名用下划线"_"拼接。
- 调用oc方法,在初始化js上下文JSContext时通过注入oc方法来实现。
oc方法调用
__c()方法执行完,就转到oc动态地进行方法调用。
- 把js对象转为oc对象,得到实例对象或类名、方法名、参数 。
- 获取方法参数的封装NSMethodSignature类型对象。其中对64位7.1以下系统的double和float类型参数修改为结构体类型。
- 根据方法签名创建NSInvocation类型对象。NSInvocation是调用函数的另一种方式,它将调用者,函数名,参数封装到一个对象,然后通过一个invoke函数来执行被调用的函数,其思想就是命令者模式,将请求封装成对象。
- JSPatch就是用NSInvocaiton来实现oc方法动态调用的。设置target、selector、参数后执行。在设置参数前对参数进行转换,因为js和oc之间传递对象,所以对一些int等类型要进行intValue取值操作。
- 读取返回值,对一些非对象的类型转成对象,比如int类型。把oc对象进行一层封装,作为返回值返回。
网友评论