为什么我们不需要热修复?

应用的动态能力

我其实之前在知乎有专门写过一篇文章来扯这个事情:https://zhuanlan.zhihu.com/p/25647026 当时主要是吐槽一下 Apple 禁止使用 JSPatch 等热修复框架这个热点事件。

现在一年过去了,昨天偶然被同事问起我们的应用有没有动态更新能力让我再次想了这个事情,考虑到目前工作环境与之前大有不同,刚好可以再聊一次这个话题。

什么是动态能力?一言蔽之,一种下发脚本直接运行的能力,以达到修复线上 bug 甚至是用来做需求的效果。

热修复的理论基础得益于 Objective-C 强大的 Runtime,通过他你可以做到下面的事情:

  • 动态调用方法
  • 动态创建类
  • 动态替换方法实现
  • 动态交换两个方法
  • 动态实现一个协议
  • 调用私有的方法
  • ...

很难说有什么事情是 Objective-C Runtime 是做不到的,如果真的想要学习 Runtime 的神奇,除了 JSPatch 以外我一般会推荐两个项目:

如果你不阅读代码,仅仅是通过使用它们你都会发现 Objective-C Runtime 是如此的强大,不仅在实现需求时是一把利器,为测试带来了方便,更催生了“热修复”这个领域。

Apple 痛恨什么

Apple 禁止掉热修复无外乎出于两个方面的考虑:

  • 防止开发人员跳过审核来上线需求
  • 防止不安全的脚本下发最终导致安全问题

可以认为 Apple 本身并不排斥通过 JavaScript 或是别的什么脚本语言来编写 iOS 应用,因为在警告风波中 React Native 和 Weex 等框架都没有受影响。Apple 真正排斥的是:通过下发脚本来执行任意的代码,这会导致不可预知的问题。

诚实地讲,React Native 和 Weex 在“动态实现需求”方面和 JSPatch 完全没有任何区别,他们完全可以干掉 Apple 在意的第一点。他们只是在“执行任意代码”方面的能力不如 JSPatch 而已。你依然可以通过 React Native 或者 Weex 实现一个审核时和用户使用时完全不一样的应用,这件事情就是我一直质疑的地方。

Apple 并没有办法把这件事情公平化、标准化,告诉我们什么是脚本,什么是程序,什么是动态变化能力,这些都没有标准。Apple 做这件事情更多的意义是给业界一个警告:你们不要给我乱来,App Store 始终是我们说了算的。

Apple 禁止不掉热修复

很遗憾的是,JSPatch 这样的库,他们使用的所有 API 都是合情合理合法的,并没有任何私有的调用和审核条款里面不允许的接口。

Apple 当时在邮件中说不能使用对 selector 相关的接口使用动态参数(例如只能使用 @selector(),这是扯淡的,我可以说绝大部分大的商业项目都对相关接口用了动态参数。Apple 这么担心的原因是当字符串变成了方法,当它能设置任何参数的时候,他就近乎拥有了一种热修复的能力(虽然现实中要处理的问题还很多),所以当时他用了这么一个宁可错杀一千不可放过一个的办法来恐吓开发者。

这事情就算放到现在来说,JSPatch 依然也是禁止不掉的,仅通过符号检查的方式,是很容易混过去的,我相信现在国内依然有大量的应用在默默的用着 JSPatch 或者自己衍生出来的轮子。为什么?因为你只要有 Objective-C Runtime 你就能这么做,你就能通过那几个有限的方法实现一个热修复,有了 Runtime 就是可以为所欲为... 禁止掉热修复从原理上来说就是不可行的。

为什么我们不需要热修复

top Created with Sketch.