最根本的原因:
OC 是动态语言,OC 上所有方法的调用/类的生成都通过 Objective-C Runtime 在运行时进行,通过类名/方法名反射得到相应的类和方法。
分析:
1.require
在JS全局作用域上创建一个同名变量,变量指向一个对象,对象属性 __clsName 保存类名,同时表明这个对象是一个 OC Class。
{
__clsName: "UIView"
}
2.这个JS对象调用“alloc”方法
如果这个JS对象没有实现alloc方法,会抛异常。
初步思想:把类名传入OC,OC 通过runtime方法找出这个类所有的方法返回给 JS,JS 类对象为每个方法名都生成一个函数,函数内容就是拿着方法名去 OC 调用相应方法。缺点:不仅要遍历当前类的所有方法,还要循环找父类的方法直到顶层,整个继承链上的所有方法都要加到JS对象上,一个类就有几百个方法,这样把方法全部加到 JS 对象上,碰到了挺严重的问题,引入几个类就内存暴涨,无法使用。
最总思想:类似 OC 的消息转发机制,使用 __C( ) 函数,传入方法名,函数内部实现 将方法名和参数信息传给 OC, OC 使用 Runtime 接口调用相应方法。
3.JS 和 OC 间的消息传递
OC 端启动 JSPatch 引擎时创建的 JSContext 实例是分装了 JavaScriptCore 框架,用于信息传递的对象。
4.方法替换的基础原理
OC 每个类对象都是一个 objc_class 的结构体如下:
实现:
1.根 JS 传过来的 类名 和 方法名 获取类Class 和 方法选择器SEL;
2.在类中寻找该方法获取到 Method 对象;
3.获取 Method 对象的 函数指针IMP 和 参数类型char;
4.新增ORIG方法函数实现指向找到的函数指针IMP(用新增方法保留原始方法实现);
5.将找到的IMP 指向 JS端实现转成 OC 的替换方法。