用JSPatch来热修补

作者: GoCac | 来源:发表于2016-01-18 21:35 被阅读964次

    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 不支持可变参数,参见官方文档

    完。

    .

    .

    .

    .

    .

    .

    .

    .

    .

    .
    ……并没有(我是有多好运这种低级错误犯了以后又撞上这样的设定

    所以,子曰曾经过:我们在使用一个框架的时候要养成研究它的原理的好习惯。

    相关文章

      网友评论

        本文标题:用JSPatch来热修补

        本文链接:https://www.haomeiwen.com/subject/mipkkttx.html