JSPatch 从入门到放弃

JSPatch 是什么

JSPatch 是一个开源项目(Github链接),只需要在项目里引入极小的引擎文件,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,替换任意 Objective-C 原生方法。目前主要用于下发 JS 脚本替换原生 Objective-C 代码,实时修复线上 bug。

JSPatch平台又是什么鬼

JSPatch需要你自己搞一个服务器管理、下发脚本,还要处理安全问题,高并发问题,烦死你。JSPatch平台封装了SDK,你只需要继承SDK就可以省去一堆的麻烦。

JSPatch 需要使用者有一个后台可以下发和管理脚本,并且需要处理传输安全等部署工作,JSPatch 平台帮你做了这些事,提供了脚本后台托管,版本管理,保证传输安全等功能,让你无需搭建一个后台,无需关心部署操作,只需引入一个 SDK 即可立即使用 JSPatch。

JSPatch 平台的 SDK 在核心代码的基础上增加了向平台请求脚本/传输解密/版本管理等功能,只用于这个平台。

通过 JSPatch 平台上传的脚本文件都会保存在七牛云存储上,客户端 APP 只跟七牛服务器通讯,支持高并发,CDN分布全国,速度和稳定性有保证。

SDK接入

这种问题不要问我,注册一个账号,建一个app获取到appid,然后接入SDK完事儿。至于你是用cocoapods还是手动接入,全凭个人喜好。SDK接入

API主要方法

+startWithAppKey:

传入在平台申请的 appKey,启动 JSPatch SDK。在-application:didFinishLaunchingWithOptions:开头初始化第三方库的时候一并调用初始化。

+sync

与 JSPatch 平台后台同步,询问是否有 patch 更新,如果有更新会自动下载并执行。

每调用一次 +sync 就会请求一次后台,如果app启动的时候检查一次就OK的话就在-application:didFinishLaunchingWithOptions:调用一次。

如果实时性要求高,就在-applicationDidBecomeActive:的时候调用。

+setupLogger:

SDK打一些请求和执行的log,默认是NSLog()输出,如果app有自己的日志系统,并且希望自己的日志系统拿到这些log,则在+startWithAppKey之前调用这个方法。

+testScriptInBundle

写好的脚本上线前总要测试一下吧,就是用这个方法。需要把main.js文件拖到项目中,并且不要调用+startWithAppKey:方法。

注意!!!:测试完成一定要删除main.js,血淋淋的教训是,如果不删除,线上的脚本down下来之后,无法确定会执行哪个main.js,莫名其妙的问题,并且很难找到。切记切记

+setupCallback:

JSPatch 执行过程中的事件回调,在以下事件发生时会调用传入的 block:

typedef NS_ENUM(NSInteger, JPCallbackType){
    JPCallbackTypeUnknow        = 0,
    JPCallbackTypeRunScript     = 1,    //执行脚本
    JPCallbackTypeUpdate        = 2,    //脚本有更新
    JPCallbackTypeUpdateDone    = 3,    //已拉取新脚本
    JPCallbackTypeCondition     = 4,    //条件下发
    JPCallbackTypeGray          = 5,    //灰度下发
};

例如
[JSPatch setupCallback:^(JPCallbackType type, NSDictionary *data, NSError *error) {
    switch (type) {
        case JPCallbackTypeUpdate: {
            NSLog(@"updated %@ %@", data, error);
            break;
        }
        case JPCallbackTypeRunScript: {
            NSLog(@"run script %@ %@", data, error);
            break;
        }
        default:
            break;
    }
}];

+setupUserData:

定义用户属性,在+sync:之前调用,用于条件下发,可以用来做AB测试。什么是AB测试?自己去Google啊...

[JSPatch setupUserData:@{
    @"userId": user.userId, 
    @"location": user.location,
    @"gender":user.gender,
    @"age":user.age
}];
条件下发
条件下发

发布补丁的时候选择条件下发,写入相应的条件就可以实现条件下发。例如图中性别是女,年龄小于35岁的用户显示特定的内容。还可以选择手机系统的版本。

+setupDevelopment

开发者预览模式,可以在 debug 模式下测试补丁效果。

[JSPatch startAppWithKey:@""];
#ifdef DEBUG
[JSPatch setupDevelopment];
#endif
[JSPatch sync];

灰度下发

这个功能太实用了,选择灰度下发可以按照比例灰度人数灰度下发。比例灰度例如随机挑选 30% 的设备生效;人数灰度比如只安装1000台设备。应用场景:

  1. 先下发一批看看效果,如果OK就全量下发
  2. 只对部分用户下发,显示特定的效果(和条件下发类似)

实战

扯了这么多终于到实战了。

背景:

  • 项目已经集成了SDK
  • 注册过了平台账号
  • 已经注册了APP获得了appkey
  • 已经上线了集成过JSPatch SDK的app
  • 这个上线的版本出现了大量的crash,crash率很高,不马上解决,老板就会马上解决你...

线上的代码是这样的,数组访问越界了

@implementation DSHomeViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  NSString *content = self.dataSource[[indexPath row]]; //可能会超出数组范围导致crash
  DSGoodsViewController *controller = [[DSGoodsViewController alloc] initWithContent:content];
  [self.navigationController pushViewController:controller];
}

@end

修改源代码

修改后的代码

@implementation DSHomeViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  if(self.dataSource.length > indexPath.row){
    NSString *content = self.dataSource[indexPath.row]; 
    DSGoodsViewController *controller = [[DSGoodsViewController alloc] initWithContent:content];
    [self.navigationController pushViewController:controller];
  }
}

@end

编写补丁脚本

打开JSPatch代码转换器,原生代码转化为JS代码

转化器
转化器

转化成功了,但是要数组,需要修改一下。常见问题 修改之后的脚本,为了能够知道脚本运行,第一行加上log

console.log('JSPatch Run Success');
require("DSGoodsViewController");

defineClass("DSHomeViewController", {
    tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {
        var row = indexPath.row();
        if (self.dataSource().length() > row) {
            var content = self.dataSource()[row];
            var controller = DSGoodsViewController.alloc().initWithContent(content);
            self.navigationController().pushViewController(controller);
        }
    }
}, {});

测试脚本

写好之后的脚本存为main.js放到项目中,在-application:didFinishLaunchingWithOptions:方法中打开测试

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     //[JSPatch startWithAppKey:myAPPKey];
    //[JSPatch sync];
    [JSPatch testScriptInBundle];
    ….
}

编译运行会看到控制台log输出JSPatch Run Success 然后......怎么能少了调试呢

在Safari中断点调试

开启 Safari 调试菜单

Safari -> 偏好设置 -> 高级 -> 勾选[在菜单栏中显示“开发”菜单]

启动app进行调试

启动APP -> Safari -> 开发 -> 选择你的机器 -> JSContext

在 iOS8 下,JSPatch 支持使用 Safari 自带的调试工具对 JS 脚本进行断点调试,界面大致长这样


JS调试器
JS调试器

上传脚本

  1. 在平台上新建一个线上的版本
  2. 把调试通过的脚本main.js上传到这个线上的版本
  3. 选择全量下发(因为要搞定crash)
  4. 删除本地的main.js
  5. 好了,等着下发之后crash率降下来,饭碗保住了

常见的问题

  1. 不能用 NSLog('xx'),应该用 console.log('xx')
  2. get property 记得加括号,例如 self.navigationItem(),而不是 self.navigationItem
  3. 私有成员变量要用 self.valueForKey()self.setValue_forKey() 接口存取
  4. block 里不能直接使用 self,应该在block外定义var myself = self;

其他更多请参见 wiki 的 基础用法常见问题

未完待续。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • 背景介绍 IOS平台提交审核的周期太长,快则45天,慢则半个月或者20天,如果碰到圣诞节等假日,可能一个月都有可能...
    恒源宾馆阅读 2,232评论 10 27
  • JSPatch 是腾讯微信团队牛人bang开源的一种通过JavaScript调用iOS原生代码来实现热修复或者动态...
    杭研融合通信iOS阅读 841评论 2 23
  • JSPatch作为热更新技术的黑科技,已经不是什么前沿的新闻了,像腾讯、美团等大公司也在使用JSPatch。前段时...
    任尔东西南北疯阅读 1,485评论 0 3
  • JSPatch简介 JSPatch 是一个开源项目(Github链接),只需要在项目里引入极小的引擎文件,就可以使...
    zyl04401阅读 2,157评论 0 6
  • 最近接触到热修复, 确实能解燃眉之急, 非常好用, 故分享给大家. 这里只讲 JSPatch, 这个是现在最热门最...
    Cean16阅读 1,437评论 2 4