JSPatch 常见问题(一)

接触JSPatch也快一年,在此总结归纳一些新接触的开发者容易碰到的一些问题。其实很多问题bang哥在wiki中已经写的很详细了,建议花点时间仔细看看下面这两个WiKi内容。

想要了解JSPatch实现原理可以先看 JSPatch 实现原理详解

require导入类

只需要一对' ', 多个类之间用逗号 ,分隔:

require('UIView, UIColor')
复制代码
方法遇到下划线_需要特别注意

因为JSPatch是通过_来分割方法参数的,所以遇到方法本身带有_的时候需要使用__双下划线代替,否则会被识别成一个参数,导致出现类似如下的报错。

//OC方法代码如下
- (BOOL)_test_Bool {
    NSLog(@"我是oc testBool");
    return NO;
}
//JS错误调用代码如下
var  testBool = self._test_Bool();
复制代码

我们知道selector 的 一个:代表有一个参数,结合报错信息可知runtime所找的方法是带两个参数的,所以肯定跟你需要调用的方法不一致,找不到则会导致崩溃。 把JS调用代码改为下面这种即可,每个下划线_变成双_,同理如果你方法中本身是双下划线__则需要变成____四个下划线。

//JS正确调用代码如下
var  testBool = self.__test__Bool();
复制代码

如果需要替换的方法本身带有下划线,与方法调用相同,也同样需要双下划线__

__test__Bool:function(){
   console.log("我是js  testBool");
   return YES;
}
复制代码

undefined is not an object(evaluating 'self.__c')

提示意思是self这个对象不存在,结合JSPatch的使用场景可以推测出这个错误一般是由于在block中使用self引起的,解决办法参考block 里使用 self 变量。但值得注意的是,在JS中,如果报了类似的undefined is not an object aaa.bbb错误,则是因为aaa这个对象为undefined,而你又要访问一个undefined的对象属性或者方法在JS中会导致崩溃。 ####一个最简单高效获取对象类名方法 大多数需求场景下可以通过object.__clsName 的方式获取OC对象类名。不需要通过isKindOfClass或者NSStringFromClass(此方法需要预先添加C函数扩展)来获取,而且不需要与OC相互通信。

//替换按钮点击方法
handleBtn: function(sender) {
     var btnClassName = sender.__clsName;
     console.log("btnClassName is : " + btnClassName);
}
复制代码

下面列举一些有__clsName属性的OC对象情况。

  • JSPatch 通过hook消息转发forwardInvocation: 方法,在调用替换方法或者新添加的方法时给参数添加了__clsName标记来保存类名(所以类似图一的sender参数就会有__clsName属性),但是Class、NSNumber、BOOL、CGFloat、结构体不知道还有没有o(╯□╰)o,感兴趣的可以去查看源码除外。
  • 通过 require 引入的类,所以在JS内通过init出来的对象都会有__clsName属性。
  • 属性和私有变量值和方法返回值(Class、NSNumber、BOOL、CGFloat、结构体不知道还有没有o(╯□╰)o感兴趣的可以去查看源码除外,不过这些好像需要知道类名情况比较少)
  • 欢迎补充

####OC对象和JS对象 大家在JSPatch交流群里所说的OC对象指的是从OC中获取的JS对象如var str = self.str() 或 通过JS初始化的对象var str = NSString.stringWithFormat("Hello World"),而JS对象指的是例如 var str = "我是js对象"var str = self.str().toJS()之后的JS对象。OC对象应该使用OC中相应方法,JS对象应该使用JS中相应方法。

//替换按钮点击方法
handleBtn: function(sender) {
     var btnClassName = sender.__clsName;
     console.log("btnClassName is : " + btnClassName);
      //初始化的OC对象
     var ocInitStr = NSString.stringWithFormat("Hello World")
      //获取属性得到的OC对象
     var str = self.str();
     console.log("ocInitStr 截取前5个字符:" + ocInitStr.substringToIndex(5).toJS())
      //JS对象
     var jsStr = "我是JS对象";
     console.log("jsStr 截取前4个字符:" + jsStr.substr(0,4))
}
复制代码

####JS中如何使用强转 答:不需要强转,直接当成强转之后的类型使用,JS里面没有类型的概念,都是对象。 ####枚举 直接使用值 Note:可在Xcode用NSLog打印查看具体值

####Block还未被赋值就被调用的问题 js exception, msg: block is not a function. (In 'block(xxx,...., xxx)', 'block' is false) 类似的报错通常是因为你获取的block还没有被赋值,所以在js中没有正确的执行,解决办法是获取到block之后,判断是否存在:

//示例方法
xxxfunction: function(sender) {
     var block = self.testBlock();
     if(block){//加上这个判断
          //do something with block
          block(xxx,...,xxx);
      }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值