JSPatch是什么
借用一下官方文档第一段
JSPatch 是一个开源项目,只需要在项目里引入极小的引擎文件,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,替换任意 Objective-C 原生方法。目前主要用于下发 JS 脚本替换原生 Objective-C 代码,实时修复线上 bug。 ——bang590
JSPatch使用中遇到的坑
CATCH的2.4.0中我们第一次加入了这个框架,今天正式的使用了一下。JSpatch功能的强大不需多言,这里记录一下使用中遇到的问题。
ViewController
用JSPatch修复controller的时候一定要加上或者重写(哪怕这两个方法没有修复的必要)这两个方法,否则分别会在willAppear的时候和willdisappear的时候崩给你看。
defineClass('ViewController', {
viewWillAppear: function(animated) {
self.super().viewWillAppear(animated);
//balabala...
},
viewWillDisappear: function(animated) {
self.super().viewWillDisappear(animated);
//balabala...
},
});
可变参数
本来要解决的问题很简单很蠢,有这样一个AlertView(CATAlertView是我们封装过的AlertView
WS(weakSelf);
CATAlertView* alert = [[CATAlertView alloc] initWithTitle:@"提示" Message:@"确定后订单被锁定,将无法被修改。" Hidden:NO touchBlock:^(id sender, NSInteger index) {
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Order" bundle:nil];
CATPaymentViewController* viewController = [storyboard instantiateViewControllerWithIdentifier:@"CATPaymentViewController"];
viewController.order = weakSelf.order;
[weakSelf.navigationController pushViewController:viewController animated:YES];
} cancelButtonTitle:@"取消" andButtonsTitles:@"付款", nil];
[alert show];
在touchBlock中缺少了判断
if(index == 1){
}
导致点击取消按钮也会触发响应。是不是很简单很蠢,ha?
被报告了这个bug以后,我打算随手fix掉得时候,突然想到正好可以试一试用js来修,实践一下,说干就干,两秒钟写好修复代码
WS(weakSelf);
CATAlertView* alert = [[CATAlertView alloc] initWithTitle:@"提示" Message:@"确定后订单被锁定,将无法被修改。" Hidden:NO touchBlock:^(id sender, NSInteger index) {
if(index == 1){
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Order" bundle:nil];
CATPaymentViewController* viewController = [storyboard instantiateViewControllerWithIdentifier:@"CATPaymentViewController"];
viewController.order = weakSelf.order;
[weakSelf.navigationController pushViewController:viewController animated:YES];
}
} cancelButtonTitle:@"取消" andButtonsTitles:@"付款", nil];
[alert show];
两秒钟利用作者提供的转换器JSPatch Convertor转换成JS代码
require('CATAlertView,UIStoryboard');
WS(weakSelf);
var alert = CATAlertView.alloc().initWithTitle_Message_Hidden_touchBlock_cancelButtonTitle_andButtonsTitles("提示", "确定后订单被锁定,将无法被修改。", NO, block('id,NSInteger', function(sender, index) {
var storyboard = UIStoryboard.storyboardWithName_bundle("Order", null);
var viewController = storyboard.instantiateViewControllerWithIdentifier("CATPaymentViewController");
viewController.setOrder(weakSelf.order());
weakSelf.navigationController().pushViewController_animated(viewController, YES);
}),"取消", "付款", null);
alert.show();
两秒钟修改一下语法错误,比如这个
WS(weakSelf);
需要改成(详见官方文档
var weakSelf = __weak(self);
以及需要注意,转换得到的JS代码中竟然把if(index==1)给弄没了,这里也需要补上......总之最后得到的JS代码是这样的
require('CATAlertView,UIStoryboard');
var weakSelf = __weak(self);
var alert = CATAlertView.alloc().initWithTitle_Message_Hidden_touchBlock_cancelButtonTitle_andButtonsTitles("提示", "确定后订单被锁定,将无法被修改。", NO, block('id,NSInteger', function(sender, index) {
if(index == 1){
var storyboard = UIStoryboard.storyboardWithName_bundle("Order", null);
var viewController = storyboard.instantiateViewControllerWithIdentifier("CATPaymentViewController");
viewController.setOrder(weakSelf.order());
weakSelf.navigationController().pushViewController_animated(viewController, YES);
}
}),"取消", "付款", null);
alert.show();
然后运行,执行这段代码,不出所料的崩溃了,崩溃点在alertview处理传进来的otherButtonTitle上(抱歉这个地方忘记截图备案了,THANKSGOD我们自己封装了一下alertView才让我们很容易定位到了崩溃点,否则估计就是红红的BAD_XXXX_XXX。不断地踩坑研究代码、查资料后终于发现了官方wiki中提到的这个点
在 JSPatch 不支持调用 [NSString stringWithFormat:@""] 方法,原因是这是参数个数可变方法,JSPatch 原理是通过 NSInvocation 动态调用方法,而 NSInvocation 不支持可变参数,参见官方文档。
完。
.
.
.
.
.
.
.
.
.
.
……并没有(我是有多好运这种低级错误犯了以后又撞上这样的设定
所以,子曰曾经过:我们在使用一个框架的时候要养成研究它的原理的好习惯。