IOS热修复之JSPatch

作者: o翻滚的牛宝宝o | 来源:发表于2016-07-20 15:22 被阅读1622次
icon

前言


IOS热修复一直是关注的重点之一。由于appstore的审核上架机制的局限,新发布的版本往往要等待很长时间才能上架。如果旧版本有重大bug,并且用户不更新,那么安装了有bug版本的用户永远都不能修复(不可挽回的失误)。

所谓热修复,就是不需要重新上架就修复线上bug。去年比较流行的React Native可以解决这一问题。但是React Native需要用JS编写代码,这一点对于我来说还是很不情愿的。

IOS热修复技术我一直认为很不成熟,但是当我使用JSPatch的时候,我的观念完全改变了,这简直就是不可多得的神器!JSPatch是去年3月份第一次在GitHub上提交,也算是新事物吧。

gitHub提交截图

JSPatch简介


  • JSPatch 可以让你用 JavaScript 书写原生 iOS APP。只需在项目引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,获得脚本语言的优势:为项目动态添加模块,或替换项目原生代码动态修复 bug。

  • 作者Bang (以前一直觉得Bang博客很有清爽,特别喜欢,没想到是JSPatch的作者。。)

  • cocoaPods安装:pod 'JSPatchSDK', '~> 1.5.2'

  • gitHub地址:https://github.com/bang590/JSPatch/blob/master/README-CN.md

  • 实现原理:可以参考唐巧的文章戳这里

  • 脚本管理平台:http://jspatch.com/

  • objective-c转js工具:转换工具

JSPatch实战体验(线下)


首先我们创建一个简单的项目,导入podFile,然后添加一个Label,添上约束,随便写点字。代码如下:

- (void)viewDidLoad {
    [super viewDidLoad]; 
    self.testLabel.text = @"this is a bug";
}
简单效果

然后在AppDelegate.m中写上头文件和代码#import <JSPatch/JSPatch.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //线下使用这个代码,系统会自动查找项目中的main.js文件,然后完成热修复
    [JSPatch testScriptInBundle];
    return YES;
}

最后在项目中添加main.js文件,里面写上js代码,运行就好了。不知道怎么写js?作者早就考虑到了这点,为了方便开发者,作者写了一个oc转js的脚本工具,只要在左侧写入oc代码,右边就能装换成符合规范的js文件(真的很用心)。
工具地址

工具演示 文件中的main.js

最后运行项目看看效果吧。

成功修复了!
defineClass('ViewController', {
        viewDidLoad: function() {
        self.super().viewDidLoad();
        
        self.testLabel().setText("Hot  Fix!");
        },
        });

从js代码我们可以得出JSPatch的实现原理。首先找到ViewController类,再找到viewDidLoad:方法,将js用正则匹配或者其他方法转换成oc代码,在通过runtime机制将viewDidLoad:替换成新的方法,这样就实现了热修复。

我们再写点复杂的代码,给view上加一个Label。

复杂点代码

这里需要注意的是,CGRectMake等结构体转成js的时候,工具并不能帮我们转换成功,这也是一处Bug吧。可以参考文档:文档
正确代码如下:

require('UILabel,UIColor');
defineClass('ViewController', {
    viewDidLoad: function() {
        self.super().viewDidLoad();

        self.testLabel().setText("hotFix!");
        var label = UILabel.alloc().initWithFrame({x:100, y:100, width:100, height:100});
        label.setText("hello World");
        label.setBackgroundColor(UIColor.redColor());
        self.view().addSubview(label);
    },
});

效果:


最终效果

JSPatch实战体验(线上)


热修复,当然在线上测试才有意义。首先登入JSPatch平台(有能力的完全可以自己搭建)http://jspatch.com/注册一个账号,申请一个appKey。

测试平台

然后修改AppDelegate.m里的方法,改成线上测试。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [JSPatch startWithAppKey:@"728a7c0548d35106"];
#ifdef DEBUG
     [JSPatch setupDevelopment];
 #endif
     [JSPatch sync];
//    [JSPatch testScriptInBundle];
     return YES;
 }

把工程里的main.js移出工程,上传到平台上。这样就完成了,线上的配置。运行代码,第一次还是显示this is a bug,因为工程要把线上的main.js文件下载到本地。第二次进入就能看见hot Fix啦。

上传main.js

总结


总体体验下来,JSPatch的使用真的很简单!而且作者真的很用心,为开发者专门设计了转换工具(对于js三脚猫功夫的我简直痛哭流涕),不愧为IOS热修复第一方案。

值得注意的是,有热修复就有安全问题。如果泄露修复方法,黑客就能修改你的源代码,这一点十分恐怖。JSPatch管理平台上提供了很多加密方案比如RSA等,具体的可以自行查看开发文档开发文档

最后附上目前正在使用的app截图,阵容很强大哦~

强大阵容

我是翻滚的牛宝宝,欢迎大家评论交流~

相关文章

网友评论

  • myCastleAndKing:新手一个 第一次接触 我想问一下怎么创建main.js文件呢 我输出的是在项目中找不到main.js文件 我自己修改的文件.js后缀
    myCastleAndKing:@o翻滚的牛宝宝o 谢谢.我js文件对了,现在不输出任何提示了,但是好像上面评论的孤独的剑客的情况差不多 我是走原本方法,js里面修改的方法不走,js里面代码是工具转的加上和你文中代码对比一样的,这中是什么情况,能提供一个基础dome么
    o翻滚的牛宝宝o:新建一个文件改后缀,拖入项目中
  • qazws:厉害了,滚犊子。
  • 23d95ce2a289:线下测试可以,线上测试就不行
  • 动感超人丶:硬伤是不会js,直接转出来的有问题,看文档也没解决,比如:字典转模型这段:@Implementation TTTuoTuoBiChartModel

    + (instancetype)chartWithDict:(NSDictionary*)dict{
    return [[self alloc] initWithDict:dict];
    }

    - (instancetype)initWithDict:(NSDictionary*)dict{
    if (self = [super init]) {

    self.coin = dict[@"coin"];
    self.last_coin = dict[@"last_coin"];
    // self.create_time = [TTHelpTool timeStampWithStr:dict[@"create_time"]];
    self.create_time = dict[@"create_time"];

    if ([dict[@"type"] integerValue] == 10) {
    self.type = @"投资返息";

    }else if ([dict[@"type"] integerValue] == 20){
    self.type = @"签到获得";

    }else if ([dict[@"type"] integerValue] == 30){
    self.type = @"兑换加息券";

    }else if ([dict[@"type"] integerValue] == 40){
    self.type = @"抽奖获得";

    }else if ([dict[@"type"] integerValue] == 50){
    self.type = @"注册获得";

    }else if ([dict[@"type"] integerValue] == 60){
    self.type = @"兑换商品";

    }
    }
    return self;
    }

    @EnD
  • 动感超人丶:有几个问题想请教一下
    1:假如工程中有多个文件需要修改,那么在平台上上传脚本如何处理?(目前只修复单个文件,我测试可以的)
    2:用sarfary调试,怎么看修改结果?类似于xcode po命令。比如我想看修改后的frame
    o翻滚的牛宝宝o:@动感超人丶 可以在main.js中写多个类的。用浏览器调试没有试过,可以去官网看看支不支持。不过可以用线下模式查看补丁效果。
  • 孤独的剑客:尝试了下,js代码不执行,原来的方法也不执行,请问这个是什么原因呢
    o翻滚的牛宝宝o:@孤独的剑客 不好意思。。看错了。不用设置delegate是你的js写错了。。
    孤独的剑客:@o翻滚的牛宝宝o 在哪里设置delegate?没看到需要设置这个
    o翻滚的牛宝宝o:@孤独的剑客 看下delegate有没有设置。
  • 东方_未明:原来你是滚犊子
    o翻滚的牛宝宝o:@东方_未明 :disappointed_relieved:

本文标题:IOS热修复之JSPatch

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