iOS-JSPatch热修复

iOS热更新绕过了苹果的审核,之前有些开发者收到了警告邮件,最新通知显示如果App中包含热更新不作调整,有可能下架.JSPatch最开始用于修复严重的线上bug,后来发展为修改创建各种模块,导致偏离了最开始的初衷.

JSPatch

JSPatch源码在GitHub上面托管,可以直接拖入工程中,也可以通过CocoaPods导入:

pod 'JSPatch'

假设项目中某个按钮点击之后执行代码过程中发生了数组越界:

@interface ViewController ()

@property (strong, nonatomic) NSMutableArray *data;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.data = [[NSMutableArray alloc] init];
    [self.data addObject:@"FlyElephant"];
    [self.data addObject:@"Keso"];
    [self.data addObject:@"北京"];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)testAction:(UIButton *)sender {
    NSInteger index = 10;
    NSString *name = self.data[index];
    NSLog(@"数组%@",name);
}

@end

如果这个场景发生在生产环境中,开发人员要么重新打包上线,要么对天祈祷,JSPatch提供了第三种可能性,方法替换:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    [JPEngine startEngine];
    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"js"];
    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
    [JPEngine evaluateScript:script];
    
    return YES;
}

main.js中替换方法的代码:

require("NSMutableArray");

defineClass("ViewController", {
            testAction: function(sender) {
            var index = 0;
            var tempData = self.data().toJS();
            if (index >= 0 && index < tempData.length) {
            var name = tempData[index];
            console.log("数组:"+name);
            } else {
            console.log("索引数据不存在")
            }
            }
            }, {});

实现起来比较简单,这个实现我们只能实现本地替换,为了做到线上环境实时动态替换,就需要了解JSPatch热更新平台.

JSPatch 服务平台

Github 开源的是 JSPatch 核心代码,使用完全免费自由,若打算自己搭建后台下发 JSPatch 脚本,可以直接使用 github 上的核心代码,与 JSPatch 平台上的 SDK 无关。JSPatch 平台的 SDK 在核心代码的基础上增加了向平台请求脚本/传输解密/版本管理等功能,只用于这个平台。

如果公司体量足够完成有实力自己实现JSPatch的后台,定制自己需要的功能,出于学习目的可以注册JSPatch服务平台的账号.

按照官方指导文档,新建App

FlyElephant.png

生成公钥和私钥,mac终端执行openssl,执行以下命令:

openssl >
genrsa -out rsa_private_key.pem 1024
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

上传修复Bug的JS文件和私钥:

FlyElephant.png

App启动设置:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    [JSPatch startWithAppKey:@"AppKey"];
    [JSPatch setupRSAPublicKey:@"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN5NdQktnZ1pL8P1IXV2vJ8x+G\nSGORWCwjjUfnUwZD/bJust7JGvTXE/rt/AlnEFm\nR5U7d+7HEjI3gS14tR3ZGG/li83wmIvnMxGXfjwWQbN+EKoR7IGG6LDilqC+qDM3\nLPSwr2zkJtgsf4L2JQIDAQAB\n-----END PUBLIC KEY-----"];
    [JSPatch sync];
    return YES;
}

如果希望及时修复可DidBecomeActive唤醒App的时候同步JSPatch补丁:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    [JSPatch sync];
}

测试代码:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.data = [[NSMutableArray alloc] init];
    [self.data addObject:@"FlyElephant"];
    [self.data addObject:@"Keso"];
    [self.data addObject:@"北京"];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)testAction:(UIButton *)sender {
    NSInteger index = 10;
    NSString *name = self.data[index];
    NSLog(@"数组%@",name);
}

@end

同步更新热修复文件在Librayw文件夹下面:

Snip20170602_5.png

Swift

Swift实现方法交换需要在方法前面加入dynamic,同时需要类集成NSObject.
定义User类:

open class User:NSObject {
    
    dynamic func buyCourse() {
        print("FlyElephant---通过Swift购买图书")
    }
}

购买事件:

   @IBAction func buyAction(_ sender: UIButton) {
        
        let user:User = User()
        
        user.buyCourse()
    }

main.js 设置:

defineClass('FESwiftDemo.User', {
            buyCourse: function() {
            console.log('FlyElephant---通过JS购买课程')
            }
            })

App 启动设置:

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        let path = Bundle.main.path(forResource: "main", ofType: "js")
        do {
            let patch = try String(contentsOfFile: path!)
            
            JPEngine.start()
            JPEngine.evaluateScript(patch)
            
        } catch {}
        return true
    }

参考链接:
JSPatch源码
JSPatch服务平台
Swift方法交换

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,010评论 4 62
  • 有人笑了, 笑话我说自己是青年 我应该是中年正步入晚年 他们都这么觉得 经受挫折能自怡自得 饱受争议能目光清澄 接...
    彦米妮阅读 273评论 0 0
  • 赖玉超:我媳妇的肠粉店! 2015年11月2日东莞 我媳妇的餐饮店铺,10天前定的开张日子是今天。 今天我起来看她...
    laiyuchao阅读 271评论 0 1
  • 妈妈说,你要好好学习,长大后做一个科学家。 爸爸说:你要好好学习,长大后做一个银行家。 老师说:你要好好学习,长大...
    柒玖月阅读 323评论 6 11
  • 世界上最远的距离, 是鱼与飞鸟的距离, 一个翱翔天际, 一个却深潜海底。 阿朗: 照旧问安,望一切安好。 这...
    九月阑珊阅读 1,582评论 0 0