CocoaPods私有库的二进制化
前言
假设你已经非常熟练的使用cocoapods来管理私有库,并且实现了组件化的APP设计架构。这篇文章将会帮助你将私有库编译成二进制文件,这样做的好处是会大大缩短编译工程的时间,提升工作的效(bi)率(ge).
目标
我们当前最重要的目标是将私有库编译成二进制文件,但是也有诸多限制条件:
- 尽量做到不修改原来私有库的所有版本的任何代码
- 在任何时候都可以随意切换源码和二进制文件,以方便调试
- 所依赖的第三方库不参与二进制编译
步骤
新建私有Cocoapods库
这里我将新建一个示例的私有库工程,对制作私有Cocoapods库不是非常了解的,可以去先看看其他文章.
$ pod lib create CCDemoLib
按照提示信息依次填写选项,完成之后Xcode会被自动打开到CCDemoLib
的pod工程.删除pod目录下的ReplaceMe.m
文件.
这里,我将建立两个子库.一个CCUI
和CCNetwork
,一个CCDemo.h
的头文件.该头文件用来导入所有子库的头文件.CCDemoLib.podspec
文件如下:
Pod::Spec.new do |s|
s.name = 'CCDemoLib'
s.version = '0.1.0'
s.summary = '一个测试二进制化的私有库'
s.description = '一个测试二进制化的私有库'
s.homepage = 'https://github.com/zhahao/CCDemoLib'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'zhahao' => '506902638@qq.com' }
s.source = { :git => 'https://git.coding.net/zhahao/CCDemoLib.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'CCDemoLib/Classes/CCDemo.h'
s.subspec 'CCNetwork' do |ss|
ss.source_files = 'CCDemoLib/Classes/CCNetwork/**/*'
ss.dependency 'AFNetworking', '~> 2.3'
end
s.subspec 'CCUI' do |ss|
ss.source_files = 'CCDemoLib/Classes/CCUI/**/*'
ss.dependency 'SDWebImage', '~> 4.1.0'
end
end
执行pod install
,安装完成之后的目录结构是这样的:
![](https://img.haomeiwen.com/i3537150/fe0ed2f107fcc77a.png)
我们将工程推到远程Git仓库
➜ CCDemoLib git:(master) ✗ git add origin https://git.coding.net/zhahao/CCDemoLib.git
➜ CCDemoLib git:(master) ✗ git add .
➜ CCDemoLib git:(master) ✗ git commit -m 'init project'
➜ CCDemoLib git:(master) git push origin master
发布到私有索引库
添加完tag,推到索引库,这里其实不需要验证的,如果有错误,自然也就推送不进去.等几分钟...
➜ CCDemoLib git:(master) git tag 0.1.0
➜ CCDemoLib git:(master) git push --tags
➜ CCDemoLib git:(master) pod repo push CCPodSpec CCDemoLib.podspec --allow-warnings
然后,成功了~ 到此,我们就发布了一个正常的私有库.
二进制化
前面简单介绍了下私有库的创建,接下来介绍私有库的二进制化方案.
iOS里面的静态库分为.framework和.a两种类型,它们的区别是.framework会包含资源文件,而.a文件是不包含资源文件.一般情况下我们都需要.a类型的静态库,这样每个组件的资源都不会安装到主工程里面去,避免了资源的重复问题,但是主工程里面需要导入需要的所有的图片等资源.
下面以.framework为例子:
生成framework
直接上图:
![](https://img.haomeiwen.com/i3537150/730754da428d45da.png)
![](https://img.haomeiwen.com/i3537150/348e2f10909796b9.png)
![](https://img.haomeiwen.com/i3537150/7c88c239e08a9d2a.png)
![](https://img.haomeiwen.com/i3537150/e93263d5c19582cd.png)
![](https://img.haomeiwen.com/i3537150/6063f75917a83d9a.png)
![](https://img.haomeiwen.com/i3537150/8c44770d8488f972.png)
![](https://img.haomeiwen.com/i3537150/30aa437b4df24de1.png)
![](https://img.haomeiwen.com/i3537150/71963fa8cab0b845.png)
![](https://img.haomeiwen.com/i3537150/44984d189457ce6c.png)
![](https://img.haomeiwen.com/i3537150/ce232d45d1364a49.png)
修改podfile文件
![](https://img.haomeiwen.com/i3537150/ff21cc9fd1f52198.png)
执行 'pod install',等安装完成之后,编译刚才的CCDemoBinary
target,找到CCDemoBinary.framework,位置如下:
![](https://img.haomeiwen.com/i3537150/42796028b515f405.png)
右键show in finder 找到CCDemoBinary.framework
文件,选Release-iphoneos
文件夹里面的那个.
![](https://img.haomeiwen.com/i3537150/b7b3dd2cce621473.png)
![](https://img.haomeiwen.com/i3537150/6bf6e6cdc720482b.png)
至此,framework已经搞定了,接下来我们要去修改CCDemoLib.podspec
文件
修改CCDemoLib.podspec
之前说过,我们需要随时切换源码和二进制文件,所以我们可以利用环境变量来处理这两种情况
$ CCDemoLib_Source=1 pod install
CCDemoLib_Source
就是设置了一个环境变量,在.podspec
文件中,可以使用ENV['CCDemoLib_Source']
来获取
修改之后的CCDemoLib.podspec
文件
Pod::Spec.new do |s|
s.name = 'CCDemoLib'
s.version = '0.1.0'
s.summary = '一个测试二进制化的私有库'
s.description = '一个测试二进制化的私有库'
s.homepage = 'https://github.com/zhahao/CCDemoLib'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'zhahao' => '506902638@qq.com' }
s.source = { :git => 'https://git.coding.net/zhahao/CCDemoLib.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
if ENV['CCDemoLib_Source'] || ENV['AllLib_Source']
s.source_files = 'CCDemoLib/Classes/CCDemo.h'
s.subspec 'CCNetwork' do |ss|
ss.source_files = 'CCDemoLib/Classes/CCNetwork/**/*'
ss.dependency 'AFNetworking', '~> 2.3'
end
s.subspec 'CCUI' do |ss|
ss.source_files = 'CCDemoLib/Classes/CCUI/**/*'
ss.dependency 'SDWebImage', '~> 4.1.0'
end
else
s.source_files = 'CCDemoLib/Classes/**/*.h'
s.vendored_frameworks = 'CCDemoLib/Products/CCDemoBinary.framework'
s.dependency 'AFNetworking', '~> 2.3'
s.dependency 'SDWebImage', '~> 4.1.0'
end
end
中间的if...else...end
的逻辑中AllLib_Source
环境变量的意思是所有私有库判断,CCDemoLib_Source
是当前的私有库判断.
当设置环境变量为true,那么,我们这个pod库的source_files
和dependency
都是引用源码.否则,我们就将source_files
全部设置为头文件.并且设置vendored_frameworks
为刚才拖进来的framework,第三方库全部为依赖关系,也就是全部为源码.
- 当我想让所有私有库显示源码,只需要设置
AllLib_Source=1
- 当我们指定某一个私有库为源码,其他都为二进制,只需要设置
CCDemoLib_Source=1
- 当我们想让所有私有库都是二进制,那么就什么环境变量都不设置
测试工程的framework私有库的结构目录如下:
![](https://img.haomeiwen.com/i3537150/ebc9620757794bec.png)
可以看到,所有的.m文件全部没有了.
自此,我们就完成了大部分工作.最后就是要将修改后的所有文件提交到Git远程仓库和pod索引库.
提交修改,更新索引库
git提交修改:
➜ CCDemoLib git:(master) ✗ git add .
➜ CCDemoLib git:(master) ✗ git commit -m '二进制化该私有库'
➜ CCDemoLib git:(master) git push origin master
删除之前的tag
➜ CCDemoLib git:(master) git tag
0.1.0
➜ CCDemoLib git:(master) git tag -d 0.1.0
➜ CCDemoLib git:(master) git push origin :0.1.0
设置新的同名tag并提交
➜ CCDemoLib git:(master) git tag 0.1.0
➜ CCDemoLib git:(master) git push --tags
提交新的索引库
➜ CCDemoLib git:(master) pod repo push CCPodSpec CCDemoLib.podspec --allow-warnings
等几分钟成功之后,可以查看一下索引库是否更新了该版本的.podspec
文件.
到此为止,我们所有的操作都没有修改源码,也实现了我们之前的三个限制.
清除缓存
由于pod update
的原理是先从缓存中读取,即Podfile.lock
文件,由于我们没有修改私有库的版本号,所以我们需要先清空缓存,让索引库重新从远程拉取.podspec
文件. 所以,当你每次二进制化一个私有库成功之后,都需要清空缓存,不然执行pod install
之后都是源码,而不是二进制文件.
➜ CCDemoLib git:(master) pod cache clean --all
使用
在你的APP主工程里面,执行pod install
或者pod update
:
-
$ CCDemoLib_Source=1 pod update
只安装了CCDemoLib
私有库为源码 -
$ pod update
安装了所有私有库为二进制 -
$ AllLib_Source=1 pod update
安装了所有私有库为源码
我们新建了一个测试主工程CocoapodsBinary
platform :ios, '8.0'
use_frameworks!
source 'https://git.coding.net/zhahao/CCPodSpec.git'
source 'https://github.com/CocoaPods/Specs.git'
target 'CocoapodsBinary' do
pod 'CCDemoLib'
end
执行pod install,完成之后pod目录结构上如下:
![](https://img.haomeiwen.com/i3537150/ff53bca4f48d95de.png)
自此,我们就彻底完成了私有库的二进制!
核心
私有库的二进制化核心就是将原来的私有库编译出一个framework,然后修改.podspec
文件,根据不同的环境变量获取不同的对私有库的描述信息,这样通过pod
进行安装和更新的时候,安装了不同的文件。
下一期,我将使用fastlane来简化一些流程,避免做一些重复的操作和可能带来的操作失误.