利用Cocoapods创建基于Git的私有库podspec
由于项目要进行组件化,考虑到公司内部实现的一些私有组件,不对外公开,而又想在不同项目中使用,该怎么办呢?由于cocoapods有了强大的功能,可以自己创建podspec,更可以设置私有的库。那么利用cocoapods来管理公共组件就很方便了。
使用Cocoapods制作私有库就完美的解决了这个问题。下图就是使用私有库带给我们的好处:
Cocoapods是如何实现查找第三方库呢?如下图:
如何做?
创建一个私有的podspec包括如下那么几个步骤:
- [创建并设置一个私有的Spec Repo](#创建并设置一个私有的Spec Repo)
- 创建Pod的所需要的项目工程文件,并且有可访问的项目版本控制地址
- 创建Pod所对应的podspec文件
- 本地测试配置好的podspec文件是否可用
- [向私有的Spec Repo中提交podspec](#向私有的Spec Repo中提交podspec)
- 在项目中的Podfile中增加刚刚制作的好的Pod并使用
- 更新维护podspec
在 这一系列的步骤中需要创建两个Git仓库,分别是第一步和第二步(第二步不一定非要是Git仓库,只要是可以获取到相关代码文件就可以,也可以是SVN 的,也可以说zip包,区别就是在podspec中的source项填写的内容不同),并且第一步只是在初次创建私有podspec时才需要,之后在创建 其他的只需要从第二步开始就可以。本文只介绍在Git环境下的操作,其他环境其他方式暂不说明。
创建并设置一个私有的Spec Repo
先来说第一步,什么是Spec Repo
?它是所有的Pods
的一个索引,就是一个容器,所有公开的Pods
都在这个里面,它实际是一个Git
仓库remote
端在GitHub
上,但是 当你使用了Cocoapods
后它会被clone
到本地的 ~/.cocoapods/repos
目录下,可以进入到这个目录看到master
文件夹就是这 个官方的Spec Repo
了。这个master
目录的结构是这个样子的
.
├── Specs
└── [SPEC_NAME]
└── [VERSION]
└── [SPEC_NAME].podspec
因此,
我们需要创建一个类似于master
的私有Spec Repo
,这里我们可以fork官方
的Repo
,也可以自己创建,个人建议不fork
,因为你只是想添加自己的Pods,没有必要把现有的公开Pods
都 copy
一份。所以创建一个 Git
仓库,这个仓库你可以创建私有的也可以创建公开的,不过既然私有的Spec Repo
,还是创建私有的仓库吧,需要注意的就是如果项目中有其他同事共同开发的话,你还要给他这个Git仓库的权限。因为GitHub
的私有仓库是收费 的,我还不是GitHub
的付费用户,所以我使用了其他Git服务,我使用的是 https://git.oschina.net
,当然还有其他的可供选择开源中国、Bitbucket
以及 CSDN Code
.
创建完成之后在Terminal中执行如下命令:
命令格式 $ pod repo add [Private Repo Name] [GitHub HTTPS clone URL]
$ pod repo add MZSpecs https://git.oschina.net/Gogal/MZSpecs.git
此时如果成功的话进入到 ~/.cocoapods/repos
目录下就可以看到 MZSpecs
这个目录了。至此第一步创建私有 Spec Repo
完成。
PS:如果有其他合作人员共同使用这个私有Spec Repo的话在他有对应Git仓库的权限的前提下执行相同的命令添加这个Spec Repo即可。
检查是否安装成功:
$ cd ~/.cocoapods/repos/MZSpecs $ pod repo lint .
注意第二个命令后面的 "."不能省。
创建Pod的所需要的项目工程文件,并且有可访问的项目版本控制地址
- 创建Pod的所需要的项目工程文件
如果是有现有的组件项目,并且在Git的版本管理下,那么这一步就算完成了,可以直接进行下一步了。
如果你的组件还在你冗余庞大的项目中,需要拆分出来或者需要自己从零开始创建一个组件库,那么我建议你使用Cocoapods提供的一个工具将第二步与第三步结合起来做。
现在来说一下这个工具,相关的文档介绍是 Using Pod Lib Create 就拿我创建的 gogalLive
为例子具体讲一下这里是如何操作的,先cd到要创建项目的目录然后执行
执行命令
$ pod lib create gogalLive
在此期间需要确认下面4个问题:
Would you like to provide a demo application with your library? [ Yes / No ]
yes
Which testing frameworks will you use? [ Specta / Kiwi / None ]
None
Would you like to do view based testing? [ Yes / No ]
No
What is your class prefix?
MZ
1.是否需要一个例子工程;
2.选择一个测试框架;
3.是否基于View测试;
4.类的前缀;
4个问题的具体介绍可以去看官方文档, 我这里选择的是
1.yes;2. None;3.NO;4.MZ。
问完这4个问题他会自动执行pod install命令创建项目并生成依赖。
如果需要打包成静态库的话,需要安装cocoapods-packager插件
执行命令
$ sudo gem install cocoapods-packager
创建Pod所对应的podspec文件
pod spec create gogalLive
执行完之后,就创建了一个podspec文件,他其中会包含很多内容,可以按照我之前介绍的进行编辑,没用的删掉。编辑完成之后使用验证命令验证一下
接 下来就是向Pod文件夹中添加库文件和资源,并配置podspec
文件,我把一个网络模块的共有组件放入Pod/Classes
中,然后进入Example
文件夹执行pod update
命令,再打开项目工程可以看到,刚刚添加的组件已经在Pods子工程下Development Pods/ gogalLive
中了,然后编辑demo
工程,测试组件,我并没有使用提供的测试框架进行测试,这里就先不介绍了。
可以使用 SourceTree
等工具上传你的代码到公共仓库, 关于如何使用命令行上传代码到远端仓库, 可以移步:iOS开发使用Git那些事, 这里不做赘述.
注:这里需要注意的是每当你向Pod中添加了新的文件或者以后更新了
podspec
的版本都需要重新执行一遍pod update
命令。
测试无误后需要将该项目添加并推送到远端仓库,并编辑 podspec
文件。
通过Cocoapods
创建出来的目录本身就在本地的Git
管理下,我们需要做的就是给它添加远端仓库,同样去GitHub
或其他的Git
服务提供商那里创建一个私有的仓库,拿到SSH
地址,然后cd到gogalLive
目录
$ git add . $ git commit -s -m "Initial Commit of Library" #添加远端仓库 $ git remote add origin https://git.oschina.net/Gogal/gogalLive.git #提交到远端仓库 $ git push origin master
因为podspec文件中获取Git版本控制的项目还需要tag号,所以我们要打上一个tag,
$ git tag 0.4.8 $ git push --tags
做完这些就可以开始编辑podspec
文件了,它是一个Ruby
的文件,把编辑器的格式改成Ruby
就能看到语法高亮,下面我贴上我的podspec
文件,并在后面以注释的形式说明每个字段的含义,没有涉及到的字段可以去官方文档查阅
- 编辑
podspec
文件
# Be sure to run `pod lib lint gogalLive.podspec' to ensure this is a # valid spec before submitting. # # Any lines starting with a # are optional, but their use is encouraged # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html # Pod::Spec.new do |s| s.name = 'gogalLive' s.version = '0.4.9' s.summary = 'gogalLive是一个基于电商直播的解决方案的模块化类库' s.homepage = 'https://git.oschina.net/Gogal' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'kingly09' => 'kingly09@gmail.com' } s.source = { :git => 'https://git.oschina.net/Gogal/gogalLive.git', :tag => s.version.to_s } s.subspec 'Categories' do |categories| categories.source_files = 'Categories/ExtensionObjc/**/*' categories.public_header_files = 'Categories/ExtensionObjc/**/*.h' categories.dependency 'YYKit', '~> 1.0.9' end s.subspec 'Extension' do |extension| extension.source_files = 'Categories/CAAnimation+STExtension/**/*', 'Categories/Foundation+KYExtension/**/*', 'Categories/UIKit+KYExtension/**/*' end s.subspec 'Utils' do |utils| utils.source_files = 'Utils/DataFiltration/**/*' utils.public_header_files = 'Utils/DataFiltration/**/*.h' end s.subspec 'Models' do |models| models.public_header_files = 'Models/**/**/*.h' models.source_files = 'Models/**/**/*' models.dependency 'gogalLive/Utils' models.dependency 'gogalLive/Categories' models.dependency 'YYKit', '~> 1.0.9' end #s.dependency 'KYModel' , '~> 0.1.1' # s.subspec 'Application' do |application| # end # s.subspec 'Controllers' do |controllers| # end # s.subspec 'Views' do |Views| # end s.ios.deployment_target = '8.0' s.requires_arc = true s.frameworks = 'UIKit','Foundation', 'CoreFoundation','CoreGraphics','ImageIO','CoreLocation','Photos','QuartzCore','Security' end
编辑完podspec
文件后,需要验证一下这个文件是否可用,如果有任何WARNING
或者ERROR
都是不可以的,它就不能被添加到Spec Repo
中,不过xcode
的WARNING
是可以存在的,
本地测试配置好的podspec文件是否可用
验证需要执行一下命令:
$ pod spec lint gogalLive.podspec --sources='https://git.oschina.net/Gogal/MZSpecs.git,https://github.com/CocoaPods/Specs.git' --allow-warnings
此时由于你当前工程B依赖的工程是私有库,于是会报错:
- ERROR | [iOS] unknown: Encountered an unknown error (Unable to find a specification for
MZHttpRequest (~> 0.1.0)
depended upon byMZHttpRequest
) during validation.
原因:校验podspec文件时会到远程podspec库查找相关依赖,默认只会到官方specs库校验,此时需要指定远程specs库去校验。
解决:
- 指定pod spec文件校验地址
$ pod spec lint privateLibName.podspec --sources='http://[privateLibName]/cocoaspecs.git,https://github.com/CocoaPods/Specs.git' --allow-warnings
- 引用当前私有库的podFile中指定source为私有库地址
source http://[privateLibName]/cocoaspecs.git' source 'https://github.com/CocoaPods/Specs.git'
- 本地测试podspec文件
我们可以创建一个新的项目,在这个项目的Podfile
文件中直接指定刚才创建编辑好的podspec
文件,看是否可用。 在Podfile
中我们可以这样编辑,有两种方式
platform :ios, '8.0' source 'https://git.oschina.net/Gogal/MZSpecs.git' source 'https://github.com/CocoaPods/Specs.git' inhibit_all_warnings! pod 'gogalLive', :path => '~/code/Cocoapods/podTest/gogalLive' #指定路径 pod 'gogalLive', :podspec => '~/code/Cocoapods/podTest/gogalLive/gogalLive.podspec' #指定podspec文件
然 后执行 pod install
命令安装依赖,打开项目工程,可以看到库文件都被加载到Pods
子项目中了,不过它们并没有在Pods
目录下,而是跟测试项目一样存在于 Development Pods/gogalLive
中,这是因为我们是在本地测试,而没有把podspec
文件添加到Spec Repo
中的缘故。
在项目中编写代码,测试库文件无误后就可以开始下一步了,提交podspec
到Spec Repo
中。
向私有的Spec Repo中提交podspec
向Spec Repo
提交podspec
需要完成两点一个是podspec
必须通过验证无误,在一个就是删掉无用的注释(这个不是必须的,为了规范还是删掉吧)。 向我们的私有Spec Repo
提交podspec
只需要一个命令.
$ pod repo push MZSpecs gogalLive.podspec --allow-warnings #前面是本地Repo名字 后面是podspec名字
完成之后这个组件库就添加到我们的私有Spec Repo
中了,可以进入到 ~/.cocoapods/repos/MZSpecs
目录下查看
使用 pod search gogalLive
查找得到的结果为
-> gogalLive (0.4.9) gogalLive是一个基于电商直播的解决方案的模块化类库 pod 'gogalLive', '~> 0.4.9' - Homepage: https://git.oschina.net/Gogal - Source: https://git.oschina.net/Gogal/gogalLive.git - Versions: 0.4.9, 0.4.7, 0.4.5, 0.4.4, 0.3.0, 0.1.9, 0.1.8, 0.1.7, 0.1.6, 0.1.5, 0.1.3 [MZSpecs repo] - Subspecs: - gogalLive/Categories (0.4.9) - gogalLive/Extension (0.4.9) - gogalLive/Utils (0.4.9) - gogalLive/Models (0.4.9) (END)
将本地podspec推送到远程私有spec库时因为警告失败,如果.podspec文件存在警告时不能成功push。
解决:
pod repo push 本地spec库名 本地.podsepc文件 --allow-warnings
不过为了严谨,最好把产生的警告解决掉再推送到远程仓库,以免对你的同事造成困扰。
更多相关指令,你都可以用–help查看:
pod repo push --help
在项目中的Podfile中增加刚刚制作的好的Pod并使用
使用制作好的 Pod
在完成这一系列步骤之后,我们就可以在正式项目中使用这个私有的Pod
了只需要在项目的Podfile
里增加如下几行:
例如:
# Uncomment the next line to define a global platform for your project platform :ios, '8.0' source 'https://git.oschina.net/Gogal/MZSpecs.git' source 'https://github.com/CocoaPods/Specs.git' inhibit_all_warnings! target 'ShopLiveApp' do # Uncomment the next line if you're using Swift or would like to use dynamic frameworks use_frameworks! pod 'gogalLive', '~> 0.4.9' # Pods for ShopLiveApp target 'ShopLiveAppTests' do inherit! :search_paths # Pods for testing end target 'ShopLiveAppUITests' do inherit! :search_paths # Pods for testing end end
引用当前私有库的podFile
中指定source
为私有库地址
必须添加
source 'https://git.oschina.net/Gogal/MZSpecs.git' source 'https://github.com/CocoaPods/Specs.git'
抑制警告
inhibit_warnings参数能够有效的抑制CocoaPods引入的第三方代码库产生的warning。
可以全部指定。
inhibit_all_warnings!
也可以针对指定。
pod 'gogalLive', '~> 0.4.9', :inhibit_warnings => true
使用 Dynamic Frameworks
代替Static Libraries
通过标志use_frameworks!
就可知开启这个功能。如果需要使用Swift
的库,就必须加上这个标志了。
使用CocoaPods
来添加第三方类库,无论是执行pod install
还是pod updat
很多时候都卡在了Analyzing dependencies
不动,这是更新本地的pod spec
所以文件导致的。通过--no-repo-update
标志可以不更新本地pod spec
索引。当然首次install
不应该添加这个标志,后续修改Podfile
的时候可以适当使用,加快pod速度。
pod install --no-repo-update pod update --no-repo-update
然后执行 pod update --no-repo-update
,更新库依赖,然后打开项目可以看到,我们自己的库文件已经出现在Pods
子项目中的Pods
子目录下了,而不再是Development Pods
。
更新维护podspec
制作好的podspec文件后续的更新维护工作,比如如何添加新的版本,如何删除Pod。
因为我们创建了subspec所以项目整体的依赖dependency,源文件source_files,头文件public_header_files, 资源文件resource等都移动到了各自的subspec中,每个subspec之间也可以有相互的依赖关系,比如UIKitAddition就依赖于 CommonTools。
编辑完成之后,在测试项目里pod update一下,几个子项目都被加进项目工程了,写代码验证无误之后,就可以将这个工程push到远端仓库,并打上新的tag->1.0.0。
最后再次使用pod lib lint验证编辑好的podsepc文件,没有自身的WARNING或者ERROR之后,就可以再次提交到Spec Repo中了,命令跟之前是一样的。
如何删除一个私有Spec Repo,只需要执行一条命令即可
$ pod repo remove MZSpecs
这样这个Spec Repo就在本地删除了,我们还可以通过
$ pod repo add MZSpecs https://git.oschina.net/Gogal/MZSpecs.git
再把它给加回来。
参考资料: