Objective-C 新老静态SDK共存方案
背景 本文将介绍一种在有源码的情况下,新老版本静态SDK共存于同一应用的方法实现。 静态SDK升级并上线后,可能会发现新版本SDK有问题而老版本SDK没有问题的现象,这时对于已经升级的应用将无法直接回退到老版本SDK,除非一开始就新老版本SDK同时存在于这个应用中。 对于Objiective-C这种没有命名空间的语言,当一份代码构建出两个静态库,且两个静态库同时链接于同一个应用时(同一个应用同时链接这个两个静态库),那么将会发生符号冲突问题—-符号重定义(duplicate symbol);而解决符号重定义的办法就是将符号重命名,当然删除符号也可以—-不过这样可能引起符号为定义错误。 就Objiective-C而言,符号重命名需要修改源码。对于静态SDK工程来说,第一步是需要先将类名、函数名、全局变量名这些符号列举出来,然后逐一添加前缀或者后缀, 对于影响业务逻辑的地方还需要斟酌修改,特别是Objiective-C的运行时反射更要注意。例如像NSClassFromString,相关代码添加前缀或者后缀要仔细。 模块化拆分 这步骤不是必须,但是强烈推荐的。 就双静态SDK共存这事来看,模块化拆分的唯一目的是减少需要修改的符号数量:例如,通常情况下像AFNetworking这种工具库是没有必要添加前缀或者后缀的。 所以,拆分的唯一原则:将长期不修改的代码拆分出来,这部分可以作为双SDK的公共库。 导出符号列表 常见的方法是使用 nm 工具,可以导出SDK里的符号列表。也可采用分析 linkmap 文件的方式,导出SDK里的符号列表。 需要导出的符号有: 类名 函数名—非类所属 全局变量名 导出的全局变量名如果是静态变量名,一般不需要添加前缀或者后缀。不一般的情况,非静态全局变量引用了静态变量,这时就要处理下。 添加前缀或者后缀 这里推荐使用预编译宏技术,定义一个宏并使用 ## 连接符 #define SUFX (x) x##_我是后缀 // 类 @interface SUFX(MyClass) ---> @interface MyClass_我是后缀 [SUFX(MyClass) method] ---> [MyClass_我是后缀 method] // 函数 void SUFX(MyFunc) ---> void MyFunc_我是后缀 //变量 int SUFX(MyVar) ---> int MyVar_我是后缀 给Objective-C添加命名空间? 最后,介绍下llvm编译插件,增加命名空间语法支持,从根本上解决问题。不过,尚未完成。。。 ...