近期在项目中首次使用了CocoaPods。从软件工程的角度来看,我对目前常见的CocoaPods使用方法有些意见,建议作一些改进。先说一下我建议的最佳实践,后面再分析为何要这样作。而且但愿你们根据本身公司的状况,讨论一下这几项建议是否合理,一块儿搞出一份真正的“最佳实践”。
CocoaPods的常见使用方法参见唐巧的文章《用CocoaPods作iOS程序的依赖管理》。在他的基础上,我提出几条补充。
1. CocoaPods生成的Pods目录*不*加入.gitignore,也就是说,第三方库的源码或binary要和产品代码一块儿,提交到公司内部的版本控制系统上。每次修改Podfile并执行pod update后,把Podfile、Podfile.lock、Pods目录下的改动一并签入。
2. 保证在任什么时候候只签出一次代码就能直接编译执行,不须要执行pod命令,甚至能够不装CocoaPods就能参与开发。
3. Podfile里全部的库使用精确版本号,不使用任何’~> 1.0', ‘>= 1.0'之类的版本号语法,只使用精确的版本号如'1.3.2'。
4. 在项目开发过程当中,能够每隔一段时间使用pod outdated命令手动检查各第三方库是否有更新。若是发现某个库有新版本,去第三方库主页查看更新记录,并对版本变更作评估。若是确认有必要更新到最新版本,则修改Podfile里的版本号到最新版本,执行pod update。
5. 若是两我的同时修改了Podfile,第二我的git pull后发现有conflict,resolve顺序是:不动其余文件,先手动resolve Podfile的冲突;而后执行pod update;若是仍有冲突,能够用git reset把Podfile.lock和Pods目录恢复原状,再次执行pod update。此时应该没有pod相关的冲突了。
------------------------------------
如下分析常见CocoaPods用法的问题,首先看CocoaPods官网上的示例Podfile。
source 'https://github.com/CocoaPods/Specs.git'
pod 'AFNetworking', '~> 1.0'
这两行的含义是,使用github上的pods spec,安装AFNetworking 1.x系列最新的那个版本;若是AFNetworking还依赖于其余库,自动安装合适的版本。
假设如今咱们的项目中要用到第三方库XYZ,开发流程大体以下:
1. 项目建立者张三在本身机器上安装好CocoaPods。
2. 张三执行pod init,在Podfile里添加代码 pod 'XYZ', '~> 1.0'。执行pod install,把Podfile和Podfile.lock签入代码管理,Pods目录添加到.gitignore。
3. 项目开发人员李四安装好CocoaPods。
4. 李四签出代码,编译,发现pod报错。因而执行pod install后,从新编译经过。
这样的CocoaPods使用方法可能引起不少异常状况。考虑第一类场景:
1. Github忽然被盾了(曾经发生过)、或公司的外网出口挂了,李四没法成功执行pod install,所以只能眼巴巴的看着项目代码,没法编译。此时张三说,把我本地的Pods目录都拷给你一份吧,虽然这样拷来拷去容易出错,但暂时先这样临时解决吧。
2. Github忽然被盾了,公司的持续集成服务器上没法执行pod install,也无法给服务器拷一份Pods目录。因而连续多天没法用持续集成。
3. XYZ开发者在修改代码时,从git上删除了最新版本的tag,并从新加tag到另外一次commit上。因而张三和李四获得的XYZ代码是不一样的。(虽然AFNetworking开发者颇有经验,不太可能出这种错,但其余小的第三方库就不必定了。)
4. 五年后,早就没人使用古老的iOS 7了。XYZ开发者认为该库是针对iOS 7的,技术已经太陈旧,因而从Github上删除了该项目。(还好咱们三年前就再也不用这个库了。)但某一天公司有个新项目,想参考之前的代码。当打开代码执行pod install时,发现Github上已经没有XYZ库了。
以上状况能够归结为:你的代码是否可用严重依赖于别人。你从公司的版本控制系统上获取的代码不能直接编译,还依赖于世界各地不少其余人是否正确配置了他们的代码,还依赖于Github等git服务商是否可用,等等。在极端状况下,会有灾难性后果。
再看第二类场景:
5. 在咱们项目的开发过程当中,XYZ最新版本是1.4。一年后,咱们从新打开旧的项目代码,执行pod install,获取到XYZ 1.x系列的最新版本1.7版。在XYZ 1.4到1.7版本之间,改变了一些接口和实现,咱们的项目代码颇有可能没法编译,或没法正确执行。
这里的问题是:常见的版本号写法'~> 1.0’会在pod install或pod update时检查版本更新,随时将第三方库升级到1.x系列的最新版本。对正在开发的项目来讲,常常升级第三方库是能够的。但对已经发布的产品代码,这个变更是不可接受的。已发布的版本必需要有一份固定不变的代码,不然配置管理就失去了意义。
还有第三类场景:
6. 张三的CocoaPods安装的很早,和李四机器上的不是同一版本。这两个版本的CocoaPods对依赖规则的resolve算法不一样,所以李四pod install失败,没法下载到和张三相同的第三方库代码。这是真事,两周前咱们刚刚遇到了,后来解决方法是全部人都强制安装某个旧版本的CocoaPods。
这里的问题是:CocoaPods做为开发工具链中重要的一环,它的质量是否有保证?CocoaPods不是苹果官方的工具,也不是像git那样由极富经验的人组织设计开发,咱们可否信任它的版本兼容性?具体来讲,即无论用什么版本的CocoaPods,pod install后获得基本相同的第三方库。咱们看到最近已经出了一个bug,若是时间再长点,三年后的CocoaPods会不会跟今天有较大差别?
对这个问题的一个解决方法是要求全部项目成员安装相同版本的CocoaPods,甚至安装相同版本的Ruby。但一我的须要同时参与多个项目的怎么办?问题的根源仍是没变。
------------------------------------
基于以上分析,我提议的“最佳实践”解决了如下问题。
* Pods目录签入到版本控制系统,使产品代码没有外部依赖,无论何时都能从公司内网获取一份可直接运行的代码。
* 已发布版本的产品代码永久固定,不会随时间而变化,方便追踪问题和存档。
* 不要求项目成员装一样版本的CocoaPods,甚至能够不装CocoaPods。下降测试、设计人员使用代码的难度,也避免了CocoaPods自己兼容性引发的问题。
转自:http://www.weibo.com/p/1001603800875490492754