之前面试的时候,遇到一个问题:
问:
你知道如何在崩溃日志里面发现有一处代码总是出错,但是因为版本迭代提审很麻烦,你有什么好办法吗?
答:
我会收集好这些崩溃日志,根据日志里面的崩溃信息找到对应的代码,进行更改,在下一个版本去解决这些问题(心中想的是:居然想给我下套,还好我机智,怎么可能有这样的技术,apple会让你这样玩吗)
但是兄弟们,真的是有技术能够解决这个问题,这个黑科技是JSPatch
如果你觉得这个技术不怎么样,或者有安全问题,也不必担心,下面app随便哪个你都认识吧!有了这个技术,你就再也不用每次提心掉胆的打开崩溃了好几十页的崩溃统计列表了。
废话不多说,下面看看如何接入JSPatch
1.http://www.jspatch.com/Apps/index 注册账号
2.新增app
完成后会看到APPKey
3.SDK下载和接入(这绝对是我见过最舒服的引入sdk了,好轻量级)
下载 SDK 后解压,将 JSPatch.framework 拖入项目中,勾选 "Copy items if needed",并确保 "Add to target" 勾选了相应的 target。
添加依赖框架:TARGETS -> Build Phases -> Link Binary With Libraries -> + 添加 libz.dylib 和 JavaScriptCore.framework。
4.代码部分
"AppDelegate.h"
#import "AppDelegate.h"
#import
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//这个是用来做条件下发的
[JSPatch setupUserData:@{
@"userId": @"10086"
}];
[JSPatch startWithAppKey:@"6504152e5bc93134"];
//用来检测回调的状态,是更新或者是执行脚本之类的,相关信息,会打印在你的控制台
[JSPatch setupCallback:^(JPCallbackType type, NSDictionary *data, NSError *error) {
NSLog(@"error-->%@",error);
switch (type) {
case JPCallbackTypeUpdate: {
NSLog(@"更新脚本 %@ %@", data, error);
break;
}
case JPCallbackTypeRunScript: {
NSLog(@"执行脚本 %@ %@", data, error);
break;
}
case JPCallbackTypeCondition: {
NSLog(@"条件下发 %@ %@", data, error);
break;
}
case JPCallbackTypeGray: {
NSLog(@"灰度下发 %@ %@", data, error);
break;
}
default:
break;
}
}];
//这段代码是RSA加密用的
// [JSPatch setupRSAPublicKey:@"-----BEGIN PUBLIC KEY-----
//\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8P66v+JKESIldyMh
//1Q+eZ/Nuo\nsaVdyqRfHasuujXP7NQZxtcoUiqziKnG7DoOduuEcYCRqIb//oS
//zVTDf2f/H92dmVA\nf2Pjknt8hrgtjW5Eyn4wYibla3aQZNatVQw1mktpG//ol3
//eO5tR7JzZ7P1G9RR7SLX\ngehtEmam5ZLLS6BajwIDAQAB\n-----END //PUBLIC KEY-----"];
//因为是demo,处于DEBUG,所以这里 [JSPatch setupDevelopment]; 会去执行该方法,所以带回我们在
#ifdef DEBUG
[JSPatch setupDevelopment];
#endif
[JSPatch sync];
return YES;
}
一个个来解释
1.---》[JSPatch setupUserData:@{ @"userId": @"10086" }];
这个用来做条件下发,后面会单独解释
2.---》 [JSPatch startWithAppKey:@"6504152e5bc93134"];
后面的参数,是你添加app时候拿到的appkey
3.---》 [JSPatch setupCallback:^(JPCallbackType type, NSDictionary *data, NSError *error) { }];
和jspatch平台进行请求交互之后,得到的回调,分别对应在平台上面是直接执行js,还是更新等等。
4.这里需要注意一下
ifdef DEBUG
[JSPatch setupDevelopment];
endif
[JSPatch sync];
我们做 demo都是在DEBUG的情况下,这时候执行 [JSPatch setupDevelopment];
这时候,是一个坑,需要你在发布补丁的地方,千万要选择 “开发预览”,不然没有效果
-------华丽分割线,到这里xcode上面的代码完毕-------
------下面做的主要工作是找到你的bug,然后借助js代码修正-----
下面我们要做的事情是
我们需要将oc代码替换称为js代码,这里虽然有
http://bang590.github.io/JSPatchConvertor/
这个网站可以将oc代码全部转换js代码
但是,这里有坑,这里有坑,这里有坑
比如说想要改达到上图的效果,伟大的iOS程序猿一眼就知道要修改- (void)test
于是像下面这样,这是错的
正确的步骤应该是
1.锁定你的代码,需要修改什么
2.来这个网站找到对应的js代码
https://github.com/bang590/JSPatch/wiki/JSPatch-基础用法
我们要做的是覆盖某个类的某个方法,在基础语法里面找到对应的代码
方法
3.写好你的oc代码
- (void)test{
self.testlabel.text = @"哈哈哈哈";
}
4.将oc代码转换为js代码
http://bang590.github.io/JSPatchConvertor/
test: function() {
self.testlabel().setText("啦啦啦");
}
5.进行拼接(拼接2+4的代码)
defineClass("ViewController", {
test: function() {
self.testlabel().setText("1111111);
},
})
6.生成一个名字为“main.js”的文件,只能是这个名字,将5的代码写入进去
7.进行下发
a.添加app版本,这里如果想要js代码能够生效,这里的版本号和你的app的版本号一致
b.上传你的main.js,因为是demo ,所以这里选择“开发预览”模式
这样即可
可能会遇到的问题
1.报错AppTransportSecurity,就在info.plist里面加入下面这个键值对
NSAppTransportSecurity
NSAllowsArbitraryLoads
2.为什么第一次没有效果
第一次进去的时候,只会将当前的饿代码给替换,第二次进去就发现“啦啦啦”,已经变成“嘻嘻嘻”了
补充:
1.下发的模式选择
1.开发预览,给debug模式使用的
2.全量下发,顾名思义
3.条件下发,这里注册对应的userid等等条件,与你的条件下发对应上,这个主要是针对不同的用户,修改不同的代码
AppDelegate.h
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[JSPatch setupUserData:@{
@"userId": @"10085",@"name": @"bang"
}];
}
4.灰度下发,只下发多少百分比的用户,可以下规模下发一些代码作为检测,等时机成熟,再进行全量下发
RSA加密,目前还没有接入,但是已经踩了好几个坑了
但是生成公钥和私钥的时候,文档给的代码要分开执行,最终得到这个,要打开这个文件,需要用到sublime
,
相关的网站
--》官网 http://www.jspatch.com
--》基本语法 https://github.com/bang590/JSPatch/wiki/JSPatch-基础用法
--》oc-》js网站 http://bang590.github.io/JSPatchConvertor/
最后给那些没有耐心的兄弟们上demo,自己看吧,github
https://github.com/knightSaber/jspatch.git