厚积薄发-JSPath

1.require

在全局作用域上创建一个同名变量,指向一个对象。

{
  __isCls: 1,
  __clsName: "UIView"
}

2.UIView.alloc

__c元函数 :调用一个不存在方法时,转发到一个指定函数去执行。

在oc执行JS脚本前,通过正则把所有的方法调用改成调用__c函数,再执行JS脚本。如:

UIView.alloc().init()
->
UIView.__c('alloc')().__c('init')()

并给JS对象的基类Object添加__c成员变量,其所有子类都可调用__c.

 return _methodFunc(self.__obj, self.__clsName, methodName, args, self.__isSuper)

把要调用的类名和oc方法传递给oc。

3.传递消息

JSContext *context = [[JSContext alloc] init];
context[@"hello"] = ^(NSString *msg) {
    NSLog(@"hello %@", msg);
};
[_context evaluateScript:@"hello('word')"];

OC提供了一个JavaScriptCore 库,用来和js进行交互。

JSContext 是JS代码的执行环境,可以给JSContext添加方法。如上代码,就是给Context添加hello方法。

evaluateScript("var num = 5+5 ")-->运动JS代码。

JSValue包装了可能是JS的值(字符串,数字,数组,字典,对象,方法等)。

4.对象方法 

如:UIView.alloc().

这个对象在 JS 无法使用,但在回传给 OC 时 OC 可以找到这个对象。然后返回一个对象指针给JS,在__c函数里把这个对象指针以及它要调用的方法名传给oc。

将oc对象封装成一个字典的形式:{__obj: [OC Object 对象指针]}。

5.类型转换 

JS 把要调用的类名/方法名/对象传给 OC 后,OC 调用类/对象相应的方法是通过 NSInvocation 实现

a.取得要调用的 OC 方法各参数类型,把 JS 传来的对象转为要求的类型进行调用。
b.根据返回值类型取出返回值,包装为对象传回给 JS。

6.方法替换 forwardInvocation

让每个需要被js替换的方法调用最后都调用-forwardInvocation。

  1. 把UIViewController的 -viewWillAppear: 方法通过 class_replaceMethod() 接口指向 _objc_msgForward,这是一个全局 IMP,OC 调用方法不存在时都会转发到这个 IMP 上,这里直接把方法替换成这个 IMP,这样调用这个方法时就会走到 -forwardInvocation:

  2. 为UIViewController添加 -ORIGviewWillAppear:-_JPviewWillAppear: 两个方法,前者指向原来的IMP实现,后者是新的实现,稍后会在这个实现里回调JS函数。

  3. 改写UIViewController的 -forwardInvocation: 方法为自定义实现。一旦OC里调用 UIViewController 的 -viewWillAppear: 方法,经过上面的处理会把这个调用转发到 -forwardInvocation: ,这时已经组装好了一个 NSInvocation,包含了这个调用的参数。在这里把参数从 NSInvocation 反解出来,带着参数调用上述新增加的方法 -JPviewWillAppear: ,在这个新方法里取到参数传给JS,调用JS的实现函数。

  4. 在替换 -forwardInvocation: 方法前会新建一个方法 -ORIGforwardInvocation:,保存原来的实现IMP,在新的 -forwardInvocation: 实现里做了个判断,如果转发的方法是我们想改写的,就走我们的逻辑,若不是,就调 -ORIGforwardInvocation: 走原来的流程。

6.新增方法

defineClass 定义的方法会经过 JS 包装,变成一个包含参数个数和方法实体的数组传给OC,OC会判断如果方法已存在,就执行替换的操作,若不存在,就调用 class_addMethod() 新增一个方法,通过传过来的参数个数和方法实体生成新的 Method,把 Method 的参数和返回值类型都设为id。这里 JS 调用新增方法走的流程还是 forwardInvocation 这一套。

a. 协议:

参数不全为id:

在 JS 定义类时给出实现的 protocol,这样在新增 Protocol 里已定义的方法时,参数类型会按照 Protocol 里的定义去实现:

defineClass("JPViewController: UIViewController <UIAlertViewDelegate>", {
  alertView_clickedButtonAtIndex: function(alertView, buttonIndex) {
    console.log('clicked index ' + buttonIndex)
  }
})

b.属性

通过set和get方法给对象动态添加成员变量(关联)

7 self 和super关键字

self:在js中为全局变量,调用前,self=当前对象,调用后置空。

super 添加__isSuper:1  oc中,调用super方法,找到superClass的IMP,新增一个方法,指向这个IMP.调用这个方法。

 

转载于:https://www.cnblogs.com/JShuo/p/5940186.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值