Rollout 创建了能绕开 AppStore 评审流程的在线更新(live-update)原生 Objective-C 应用的解决方案 。它宣布该解决方案能支持Swift 了。Rollout 把这项在线更新Swift 应用的技术叫伪方法偷换(pseudo method-swizzling)。
Rollout 给 Objective-C 应用打补丁的机制是一项叫做方法偷换的动态编程技术。通过修改Objective-C 运行时将方法签名关联到一个类中的某个函数的方式,开发人员能更改该方法的实现。被偷换的方法(swizzled method)会被完全替代或者被一个从Rollout 云上下载下来的新实现简单包裹起来。Rollout 允许开发人员使用JavaScript 定义偷换方法(swizzling method),这是这项机制与苹果的指导方针兼容的关键。苹果的指导方针只允许下载在WebKit 或者JavaScript Core 上运行的代码。或者,使用预定义的模板作为Objective-C 的补丁。这些模板用来完成特定的目标,例如给方法调用添加跟踪日志、禁用方法等等。
Swift 不支持原生的方法偷换。所以正如 Rollout 的 CTO Eyal Keren 解释的,因为 Swift 没有运行时编程(runtime-programming )能力,针对 Swift 他们不得不开发出类似的东西来。简而言之,Rollout 做的就是在 Swift 中间语言层(Swift Intermediate Language,SIL)给每个方法添加一个前缀来操作应用的。方法类似如下代码:
func add(a:Int, b:Int) -> Int { if Rollout_shouldPatch(ROLLOUT_a79ee6d5a41da8daaa2fef82124dcf74) { let resultRollout : Int = Rollout_invokeReturn(Rollout_tweakData!, target:self, arguments:[a, b, origClosure: { args in return self.add(a:args[0],b:args[1]);}); return resultRollout;
在上面的代码中,Rollout_invokeReturn 负责执行一个从 Rollout 云下载的 JavaScript 函数。如果需要,该函数可以回调初始的方法。
Rollout 能在多种情境中支持Objective-C。尽管Rollout 在努力改进,但相比Rollout 对Objective-C 的支持而言, Rollout 对 Swift 的支持仍然在起步阶段。尤其是:
- Swift 补丁不能执行原生的 Swift 方法,除非该方法就是被打补丁的方法或者带有 @objc 的方法。它也不能创建原生的 Swift 对象。
- 仅仅能覆盖有限类型的返回值,例如 String、Number、Optional 和所有与 Objective-C 兼容的类。
- 不能捕获 Swift 的原生异常。
- 仍然不支持 Swift 的一些特性,例如静态类方法、重载实例方法、struct 方法等等。
Rollout 证实,以上列举的一些限制已经实现了,当前正处于 beta 测试中。
Rollout 表明,它们的在线更新解决方案当前正用于数以千计的移动应用程序,绝对是符合苹果指导方针的正统解决方案。
查看英文原文: Rollout Aims to Enable Live Updates for Swift iOS Apps
感谢冬雨对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论