JSPatch – 动态更新iOS APP
原文:http://blog.cnbang.net/works/2767/
JSPatch是最近业余做的项目,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的原生接口,获得脚本语言的能力:动态更新APP,替换项目原生代码修复bug。
用途
是否有过这样的经历:新版本上线后发现有个严重的bug,可能会导致crash率激增,可能会使网络请求无法发出,这时能做的只是赶紧修复bug然后提交等待漫长的AppStore审核,再盼望用户快点升级,付出巨大的人力和时间成本,才能完成此次bug的修复。
使用JSPatch可以解决这样的问题,只需在项目中引入JSPatch,就可以在发现bug时下发JS脚本补丁,替换原生方法,无需更新APP即时修复bug。
例子
|
01
02
03
04
05
06
07
08
09
10
|
@implementation JPTableViewController...- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *content = self.dataSource[[indexPath row]]; //可能会超出数组范围导致crash JPViewController *ctrl = [[JPViewController alloc] initWithContent:content]; [self.navigationController pushViewController:ctrl];}...@end |
上述代码中取数组元素处可能会超出数组范围导致crash。如果在项目里引用了JSPatch,就可以下发JS脚本修复这个bug:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
#import “JPEngine.m"@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ [JPEngine startEngine]; [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cnbang.net/bugfix.JS"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (script) { [JPEngine evaluateScript:script]; }}]; …. return YES;}@end |
|
01
02
03
04
05
06
07
08
09
10
11
12
|
//JSdefineClass("JPTableViewController", { //instance method definitions tableView_didSelectRowAtIndexPath: function(tableView, indexPath) { var row = indexPath.row() if (self.dataSource().length > row) { //加上判断越界的逻辑 var content = self.dataArr()[row]; var ctrl = JPViewController.alloc().initWithContent(content); self.navigationController().pushViewController(ctrl); } }}, {}) |
这样 JPTableViewController 里的 -tableView:didSelectRowAtIndexPath: 就替换成了这个JS脚本里的实现,在用户无感知的情况下修复了这个bug。
更多的使用文档和demo请参考github项目主页。
原理
JSPatch用iOS内置的JavaScriptCore.framework作为JS引擎,但没有用它JSExport的特性进行JS-OC函数互调,而是通过Objective-C Runtime,从JS传递要调用的类名函数名到Objective-C,再使用NSInvocation动态调用对应的OC方法。详细的实现原理以及实现过程中遇到的各种坑和hack方法会另有文章介绍。
方案对比
目前已经有一些方案可以实现动态打补丁,例如WaxPatch,可以用Lua调用OC方法,相对于WaxPatch,JSPatch的优势是:
1.JS语言
JS比Lua在应用开发领域有更广泛的应用,目前前端开发和终端开发有融合的趋势,作为扩展的脚本语言,JS是不二之选。
2.符合Apple规则
JSPatch更符合Apple的规则。iOS Developer Program License Agreement里3.3.2提到不可动态下发可执行代码,但通过苹果JavaScriptCore.framework或WebKit执行的代码除外,JS正是通过JavaScriptCore.framework执行的。
3.小巧
使用系统内置的JavaScriptCore.framework,无需内嵌脚本引擎,体积小巧。
4.支持block
wax在几年前就停止了开发和维护,不支持Objective-C里block跟Lua程序的互传,虽然一些第三方已经实现block,但使用时参数上也有比较多的限制。
相对于WaxPatch,JSPatch劣势在于不支持iOS6,因为需要引入JavaScriptCore.framework。另外目前内存的使用上会高于wax,持续改进中。
风险
JSPatch让脚本语言获得调用所有原生OC方法的能力,不像web前端把能力局限在浏览器,使用上会有一些安全风险:
1.若在网络传输过程中下发明文JS,可能会被中间人篡改JS脚本,执行任意方法,盗取APP里的相关信息。可以对传输过程进行加密,或用直接使用https解决。
2.若下载完后的JS保存在本地没有加密,在未越狱的机器上用户也可以手动替换或篡改脚本。这点危害没有第一点大,因为操作者是手机拥有者,不存在APP内相关信息被盗用的风险。若要避免用户修改代码影响APP运行,可以选择简单的加密存储。
其他用途
JSPatch可以动态打补丁,自由修改APP里的代码,理论上还可以完全用JSPatch实现一个业务模块,甚至整个APP,跟wax一样,但不推荐这么做,因为:
- JSPatch和wax一样都是通过Objective-C Runtime的接口通过字符串反射找到对应的类和方法进行调用,这中间的字符串处理会损耗一定的性能,另外两种语言间的类型转换也有性能损耗,若用来做一个完整的业务模块,大量的频繁来回互调,可能有性能问题。
- 开发过程中需要用OC的思维写JS/Lua,丧失了脚本语言自己的特性。
- JSPatch和wax都没有IDE支持,开发效率低。
若想动态为APP添加模块,目前React Native给出了很好的方案,解决了上述三个问题:
- JS/OC不会频繁通信,会在事件触发时批量传递,提高效率。(详见React Native通信机制详解)
- 开发过程无需考虑OC的感受,遵从React框架的思想进行纯JS开发就行,剩下的事情React Native帮你处理好了。
- React Native连IDE都准备好了。
所以动态添加业务模块目前还是推荐尝试React Native,但React Native并不会提供原生OC接口的反射调用和方法替换,无法做到修改原生代码,JSPatch以小巧的引擎补足这个缺口,配合React Native用统一的JS语言让一个原生APP时刻处于可扩展可修改的状态。
目前JSPatch处于开发阶段,稳定性和功能还存在一些问题,欢迎大家提建议/bug/PR,一起来做这个项目。
JSPatch – 动态更新iOS APP的更多相关文章
- JSPatch动态更新APP
JSPatch,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的原生接口,获得脚本语言的能力:动态更新APP,替换项目原生代码修复bug. 用途 是否有过这样 ...
- JSPatch 动态更新,bug修复
本文贴出项目中热修复的代码片段: require('UIView, JPObject, HtmlAllViewController,DataManager,EMClient,EaseMessageVi ...
- IOS App动态更新
框架 JSPatch WaxPatch react-native 方案对比 目前已经有一些方案可以实现动态打补丁,例如WaxPatch,可以用Lua调用OC方法,相对于WaxPatch,JSPat ...
- JSPatch 可以让你用 JavaScript 书写原生 iOS APP
简介 JSPatch 可以让你用 JavaScript 书写原生 iOS APP.只需在项目引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,获得脚本 ...
- iOS 利用 Framework 进行动态更新
http://nixwang.com/2015/11/09/ios-dynamic-update/ 前言 目前 iOS 上的动态更新方案主要有以下 4 种: HTML 5 lua(wax)hotpat ...
- ios app 实现热更新(无需发新版本实现app添加新功能)
目前能够实现热更新的方法,总结起来有以下三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的iOS应用 ios app可以在运行时从服务器拉取最新的js文件到 ...
- ios app 实现热更新(无需发新版本号实现app加入新功能)
眼下可以实现热更新的方法,总结起来有下面三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的ios应用 ios app能够在执行时从server拉取最新的js ...
- iOS App Store上架新APP与更新APP版本
iOS App Store上架新APP与更新APP版本 http://www.jianshu.com/p/9e8d1edca148
- 微软Azure配置中心 App Configuration (三):配置的动态更新
写在前面 我在前文: <微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core>已经介绍了Asp.net Core怎么轻易的接入azure ...
随机推荐
- CnBlog客户端Windows Live Write安装方法
官方帮助http://space.cnblogs.com/forum/topic/8550 注:如果自动配置没有成功,需要手动配置: a) 在"Type of weblog that yo ...
- iOS架构师之路:慎用继承
最近在看大神Casa的文章<跳出面向对象思想(一) 继承>,脑洞大开.文章给我们展示了一个随着产品需求不断变化的例子,该例子中通过继承实现不同页面的搜索视图和搜索逻辑的代码复用,随着产品需 ...
- C语言程序设计第九次作业
一.学习内容 本次课我们重点学习了怎样向函数传递数组,鉴于大家对函数和数组的理解和运用还存在一些问题,下面通过一些实例加以说明,希望同学们能够认真阅读和理解. 例1:火柴棍拼数字 ...
- python wordcloud 对电影《我不是潘金莲》制作词云
上个星期五(16/11/18)去看了冯小刚的最新电影<我不是潘金莲>,电影很长,有点黑色幽默.看完之后我就去知乎,豆瓣电影等看看大家对于这部电影的评价.果然这是一部很有争议的电影,无论是在 ...
- JS总结 本地对象2 BOM DOM
string对象 定义一个字符: var str = "world"; str.length 返回字符长度,5 str.charAt(2) 返回字符串第2个字符(从0开始,下 ...
- Android开发学习笔记:Intent的简介以及属性的详解【转】
一.Intent的介绍 Intent的中文意思是“意图,意向”,在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述 ...
- The next day to learn English
if you smail when no one else is around,you really meat it.
- Kali安装小问题解决及一些设置
昨天按照完Kali linux之后,更改了镜像源, 然后运行了 apt-get update && apt-get dist-upgrade 发现要 等大约两个小时才能跟新完毕.. 于 ...
- ASP.NET空网页生成默认代码注释
当在Visual Studio下生成ASP.NET空网页时,默认生成代码: <%@ Page Language="C#" AutoEventWireup="true ...
- ray与triangle/quad求交二三事
引擎中,ray与quad求交,算法未细看,但有求解二次方程,不解.ray与triangle求交,使用的是97年经典算法,仔细看过论文,多谢小武同学指点,用到了克拉默法则求解线性方程组.想模仿该方法,做 ...