2015-06-25 14:25:32 +0000

使用JSPatch给iOS APP打补丁

  在我们的iOS应用中就算是已经上线了,也会存在一些bug,我们想修复这些小bug,而又不想重新经历 发包 这个繁复的过程。怎么办呢,最简单的方法就是在线打补丁。

  苹果在iOS7中提供了JavaScriptCore.framework框架。这让OC和JavaScript可以相互调用。虽然苹果官方是禁止下载在线代码运行,但是通过JavaScriptCore动态改变app的行为还是可行的。 关于JavaScriptCore的入门介绍,这里有一篇blog,可以读一下。cocoachina上还找到了一篇。而我们要介绍的JSPatch也是基于JavaScriptCore框架和runtime做的。

  这样我们就可以在Server端放置patch,等app启动的时候先去下载补丁,之后JSPatch会在runtime替换目标方法的实现,即可实现在线打补丁的目的。

  下面举个栗子project示例一下。在我们的项目中引入JSPatch,我使用的是cocoapods管理三方库的,如图:

   引入JSPatch如

  为了方便自己的使用,我们可以再对JSPatch做一层封装,因为我们要从Server端下载patch,我们可以把下载patch的操作和JSPatch的处理封装在一起,留作一个接口方便使用。JSPatch的用法,点进去看github就了解了。这样我们应用的调用逻辑只需要简单的调用这一个接口就可以了。我封装后的接口如下图:

接口图

  这个接口留了三个参数,patch在Server端的下载地址;补丁下载成功时的parser(这主要看传输数据的协议格式了);下载补丁失败时的handler。 大家可以根据自己的需求封装借口。

  下面就是在应用中的调用了。我们在应用启动的delegate方法:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中调用。

调用图

  假如我们的补丁是要修改- (void)applicationDidEnterBackground:(UIApplication *)application方法。该方法原来的实现为空,即什么都没有,现在我们要用补丁的方式让它弹出一个UIAlterView,那么js的补丁代码可以这么写:

defineClass('AppDelegate', {
    applicationWillEnterForeground: function(application) {
	    var alertView = require('UIAlertView').alloc().init()
    	    alertView.setTitle('提示')
    	    alertView.setMessage('当前为debug版本,JSPatch测试')
    	    alertView.addButtonWithTitle('OK')
    	    alertView.show()
    }
})

  效果图就不上了,静态图也不能演示这个过程,哪位有好的截取屏幕GIF图片的分享一下。

  把补丁存在沙盒内,以后再启动应用,封装的接口会先运行本地补丁,就不用下载了。补丁的运行和下载更新策略自己想吧,哈哈。


PS: 由于启动下载patch的过程是异步的,假如需要打的补丁在首页(也可能是快速操作进入了其他需要打补丁的页面),那么还没等patch下载运行,应用也已经进入了该页了,这种情况下,我们只能忍着,毕竟是处理小bug的嘛,可以忍,等再次进入该页面的时候,补丁就会运行,效果就会出来。如果逻辑设计成同步下载完成后在进入应用,在弱网环境下应用就挂掉了,得不偿失。这是我的策略,有好的想法的可以分享一下。

引用参考

JSPatch – 动态更新iOS APP