webview 加载 html5 动态更新。
react native/weex js 动态更新。
其中 waxpatch 和 jspatch 是使用较广泛的两种热修复方案。而苹果 review guideline 提到只允通过<code>javascriptcore.framework</code>或<code>webkit</code>执行脚本,因此 jspatch 是真正被 apple 官方支持的。此外鉴于<code>javascript</code>比<code>lua</code>语言更亲民,使用系统内置的 <code>javascriptcore.framework</code>而无需内嵌lua脚本引擎来解释运行lua代码,jspatch 便成为目前 ios 热修复使用最多,效果也最佳的方案。
有关上述几种热修复方案的比较可阅读这两篇文章:
<a href="http://awhisper.github.io/2016/07/22/weex-reactnative-jspatch/">weex & reactnative & jspatch</a>
jspatch 使用时需要一个后台下发和管理脚本。阿里百川 hotfix 平台帮助开发者做了这些事。通过提供脚本托管、版本管理、脚本文件及传输过程加密等服务,让开发者无需搭建后台和关心部署操作,只需引入一个 sdk 即可直接使用 jspatch 进行热修复。这个 sdk 就是 apatch(ios)。
apatch 在 jspatch 核心代码的基础上封装了向 hotfix 平台请求脚本/传输解密/脚本管理/本地调试等功能,是配合阿里百川 hotfix 平台一起使用的。
从上图可看出,客户端从服务器下载 patch 之前先要下载指定 patch 配置信息即<code>patchinfo</code>,其中包含了 patch 文件密钥 <code>file_token</code>。
服务端:
对 <code>file_token</code> 用 rsa 公钥加密。
对 <code>patchinfo</code> 原始数据采用 hmacsha1 算法计算的哈希值,并将原始数据和哈希值<code>servicetoken</code>放在同一消息中传送给客户端。
客户端:
使用 <code>secret</code> 计算所接收数据的哈希值。
检查计算所得的 hmac 是否与传送的 hmac 匹配。
只有<code>patchinfo</code>通过校验匹配后才会去下载<code>patch</code>。
另外,update patch 的接口已迁至 https,进一步保证了数据传输的安全。
本地存储的脚本被篡改的机会小很多,只在越狱机器上有点风险,对此 apatch sdk 对下载的脚本进行了aes对称加密,每次读取时:
客户端使用 rsa 私钥解密 <code>patchinfo.file_token</code> 获取 <code>key</code> 和 <code>iv</code>。
使用 <code>key</code> 和 <code>iv</code> 进行 aes 解密。
解密成功后的数据存储在 <code>script</code> 中,然后会调用 jspatch 运行js脚本的接口:
至此,apatch 的工作已经完成,接下来具体的热修复工作就交给 jspatch 了。
——jspatch wiki
“极小的引擎文件”指的就是 javascriptcore。os x mavericks 和 ios 7 引入了 javascriptcore 库,它把 webkit 的 javascript 引擎用 objective-c 封装,提供了简单、快速、安全的方式接入世界上最流行的语言:
在 objective-c 代码中直接执行 javascript 代码段;
在 javascript 语言环境里调用 objective-c 公开给 javascript的 方法;
内存管理和线程封装。
如果未接触过 javascriptcore,在深入学习 jspatch 之前有必要先了解一下这个js引擎怎么使用。
<code>jscontext</code> 是运行 javascript 代码的环境。可以在 <code>jscontext</code>中创建变量、计算、定义方法等:
<code>jsvalue</code>包装了每一个可能的 javascript 值,任何出自 <code>jscontext</code> 的值都被包裹在一个 <code>jsvalue</code> 对象中:
对 <code>jscontext</code> 和 <code>jsvalue</code> 实例使用下标可以访问之前创建的 context 的任何值。<code>jscontext</code> 需要一个字符串下标,<code>jsvalue</code> 使用字符串或整数下标来得到里面的对象和数组:
调用js方法需要使用<code>callwitharguments:</code>传递参数:
这里使用 foundation 类型<code>nsarray</code>作为参数来直接调用该函数。javascriptcore 可以 很轻松地处理这个桥接。
以上js代码都以字符串形式直接出现在oc代码中,实际中也可以在项目中引入.js文件,执行js文件中的内容。即:
从js访问在oc中定义的对象和方法有两种方式:
定义一个<code>test</code>类,遵循 <code>jsexport</code>协议:
测试: