专栏名称: CSDN
CSDN精彩内容每日推荐。我们关注IT产品研发背后的那些人、技术和故事。
目录
相关文章推荐
科技每日推送  ·  38.98万起!比亚迪空间最大SUV发布,8 ... ·  昨天  
新浪科技  ·  #屈臣氏中国利润6连跌# ... ·  2 天前  
51好读  ›  专栏  ›  CSDN

滴滴 iOS 动态化方案 DynamicCocoa 的诞生与起航

CSDN  · 公众号  · 科技媒体  · 2016-12-19 10:07

正文

作者: 孙源( @我就叫Sunny怎么了 ),滴滴出行 iOS 技术专家,多年专注于 iOS 开发,现就职于滴滴 App 架构组,在技术上做探索和深挖;善于刨根问底,对未知的东西兴趣强烈,代码风格强迫症;同时喜欢写博客( http://blog.sunnyxx.com/ ),线上线下分享,贡献开源(forkingdog)累计 star 破万。
欢迎技术投稿、约稿、给文章纠错,请发送邮件至 [email protected]


【CSDN 编者按】滴滴出行客户端 App 架构团队在对 React Native、Weex 进行调研尝试后发现并不适用于滴滴现有业务,由此自研了 iOS 动态化方案——DynamicCocoa,在这篇文章中,作者详细分享了它的背景以及具体功能实现。

方案诞生

动态化一直是 App 开发梦寐以求的能力,而在 iOS 环境下,Apple 禁止了在 Main Bundle 外加载和执行的自己的动态库,所以像 Android 一样下发原生代码的方案被堵死。

后来像 React Native、Weex 这样的基于 Web 标准的跨端方案出现,各大公司都有对其进行尝试,但对于滴滴现状,也许并不适合:

  • 滴滴 App 强交互、以地图为主体、端特异性高;

  • 客户端人员充足,跨技术栈学习和开发有较大成本;

  • 大量固化 Native 代码,重写成本高。

所以我们思考,能不能做一套 保持 iOS 原生技术栈、不重写代码就神奇的拥有动态化能力的方案呢?

于是,我们设计和实现了一个具有里程碑意义的 iOS 专属动态化方案: DynamicCocoa

DynamicCocoa 初识

DynamicCocoa 可以让现有的 Objective-C 代码转换生成中间代码(JS),下发后动态执行,相比其他动态化方案,优势在于:

  • 使用原生技术栈:使用者完全不用接触到 JS 或任何中间代码,保持原生的 Objective-C 开发、调试方式不变;

  • 无需重写已有代码:已有 native 模块能很方便的变成动态化插件;

  • 语法支持完备性高:支持绝大多数日常开发中用到的语法,不用担心这不支持那不支持;

  • 支持 HotPatch:改完 bug 后直接从源码打出 patch,一站式解决动态化和热修复需求。

不论是动态化还是 HotPatch,我们都能让开发者“Write Cocoa, Run Dynamically”。

语法支持

DynamicCocoa 能支持绝大部分日常使用的 Objective-C / C 语法,挑几个特殊的:

  • 完整的 Class 定义 interface category class extension method property ,最重要的是支持完备的 ivar 定义,保持和 native 完全一致的实例内存结构;

  • ARC :可以正确处理 strong weak unsafe_unretained 等对象的引用计数,对象的 ivar 也可以正确的释放;

  • C 函数 :支持 C 函数的定义与 C 函数的调用、内联函数的调用;

  • 可变参数 :支持 C 与 OC 的可变参数方法的调用,如 NSLog;

  • struct :支持任意结构体的使用,无需额外处理;

  • block :支持创建和调用任意参数类型的 block;

  • 其他 OC 特性 :如 @selector @protocol @encode for..in 等;

  • 其他 C 特性 :支持使用宏、static 变量、全局变量,取地址等。

举个例子,你可以放心的使用下面的写法,并能被正确的动态执行:

资源支持

一个功能模块,除了代码外,资源也是必不可少的,DynamicCocoa 的动态 bundle 支持:

  • xib 和 storyboard;

  • xcassets;

  • 不放在 xcassets 里的图片资源;

  • 其他资源文件。

对于习惯于使用 IB 来开发 UI 的人来说,这将是一个很好的开发体验。

工具链支持

我们使用 Ruby 开发了一套命令行工具( 类比为 xcodebuild ),大幅简化了配置开发环境、OC 代码转换、资源处理、打包的复杂度,它可以:

  • 解析 Xcode Project:读取工程编译选项,保持和 native 编译参数一致;

  • 增量编译:缓存 JS 转换结果,只重新转换修改过的文件,大幅提高 build 速度;

  • 链接:分析类依赖,将多个 JS 按依赖顺序合并,提高文件读取速度;

  • 资源编译:编译用到的 xib、storyboard 和 xcassets;

  • 打包:将 JS、资源等打包成 bundle。

对于开发者来说,就像 pod 命令一样,所有操作都可以通过这个命令完成。

动态插件开发流程

首先 App 中需要集成 DynamicCocoa Engine SDK,用来执行下发的 bundle 开发到发布的流程如下图所示:

当然,DynamicCocoa 只提供命令行工具和 Engine SDK,可以完成本地打包、运行和测试,而线上发布后台、服务端、CDN 等需要自行解决。

在滴滴内部,我们构建了开发、Review、线上回归测试、灰度、发布、回滚、统计的闭环系统,以服务的形式给内部接入。

HotPatch 过程

HotPatch 本质上是方法粒度上的动态化,所以在整个框架搭建起来后,HotPatch 也不难实现,使用 DynamicCocoa 做热修复的最大优势是开发者依然只对源码负责,修改完 bug 后,打个 patch 包,修复成功后把源码改动直接 push 到代码仓库就行了。

假设我们发现了下面的 bug:

然后在 Native 进行修复并自测:

自测完成后,在这个方法后面添加一个神奇的 Annotation:







请到「今天看啥」查看全文