接触JSPatch也快一年,在此总结归纳一些新接触的开发者容易碰到的一些问题。其实很多问题bang哥在wiki中已经写的很详细了,建议花点时间仔细看看下面这两个WiKi内容。
想要了解JSPatch实现原理可以先看 JSPatch 实现原理详解
require导入类
只需要一对' '
, 多个类之间用逗号 ,
分隔:
1 | require('UIView, UIColor') |
方法遇到下划线_
需要特别注意
因为JSPatch是通过_
来分割方法参数的,所以遇到方法本身带有_
的时候需要使用__
双下划线代替,否则会被识别成一个参数,导致出现类似如下的报错。
1 | //OC方法代码如下 |
我们知道selector 的 一个:
代表有一个参数,结合报错信息可知runtime所找的方法是带两个参数的,所以肯定跟你需要调用的方法不一致,找不到则会导致崩溃。
把JS调用代码改为下面这种即可,每个下划线_
变成双_
,同理如果你方法中本身是双下划线__
则需要变成____
四个下划线。
1 | //JS正确调用代码如下 |

如果需要替换的方法本身带有下划线,与方法调用相同,也同样需要双下划线__
1 | __test__Bool:function(){ |

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相互通信。
1 | //替换按钮点击方法 |


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

per
JS中如何使用强转
答:不需要强转,直接当成强转之后的类型使用,JS里面没有类型的概念,都是对象。