前言
Cocoapods是非常好用的一款iOS第三方库管理工具,使用它可以非常方便的管理和更新项目中使用到的第三方库,我们也可以把项目中的公共组件交给它去管理。Cocoapods
的介绍及优缺点本文就不再赘述。
Cocoapods
在安装之后,会在本地保存一份所有可以通过Cocoapods
安装的第三方库的索引(Spec Repo
)。这份索引中的所有项目都是公开的项目。
需求
随着项目功能越来越复杂,项目中有许多功能或者组件可以封装成类似AFNetowrk
、SDWebImage
这样的第三方库的形式来提供给项目中的其他模块使用,但是由于可能涉及到公司内部的信息,所以我们对这部分组件或模块的需求是既可以使用Pod来进行方便的管理,也需要有相关的权限才可以使用该组件或模块。
实现思路
Cocoapods
有自己创建podspec
和自定义的pods库索引(Spec Repo
)。
我们可以通过自己创建podspec
,然后把该podspec push
到我们自己创建的需要访问权限的pod索引中来实现该需求。
名词解释
-
Spec Repo
:Spec Repo
其实是一个所有Pods
的索引,所有公开的Pods都在这个里面,实际上它是一个Git仓库
的Remote端
。
在Github
上,当你使用Cocoapods
后它会被Clone
到本地的~/.cocoapods
目录下,进入这个目录可以看到一个master
文件夹,这个master
文件夹就是官方的Spec Repo
了。这个master
的目录结构是这样子的:
├── Specs
└── [SPEC_NAME]
└── [VERSION]
└── [SPEC_NAME].podspec
-
podspec
:podspec
是一个Ruby
格式的描述文件,该文件的结构是这样的:
Pod::Spec.new do |s|
s.name = "PodTestLibrary" #名称
s.version = "0.1.0" #版本号
s.summary = "Just Testing." #简短介绍,下面是详细介绍
s.description = <<-DESC
Testing Private Podspec.
* Markdown format.
* Don't worry about the indent, we strip it!
DESC
s.homepage = "https://coding.net/u/wtlucky/p/podTestLibrary" #主页,这里要填写可以访问到的地址,不然验证不通过
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" #截图
s.license = 'MIT' #开源协议
s.author = { "wtlucky" => "wtlucky@foxmail.com" } #作者信息
s.source = { :git => "https://coding.net/wtlucky/podTestLibrary.git", :tag => "0.1.0" } #项目地址,这里不支持ssh的地址,验证不通过,只支持HTTP和HTTPS,最好使用HTTPS
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>' #多媒体介绍地址
s.platform = :ios, '7.0' #支持的平台及版本
s.requires_arc = true #是否使用ARC,如果指定具体文件,则具体的问题使用ARC
s.source_files = 'Pod/Classes/**/*' #代码源文件地址,**/*表示Classes目录及其子目录下所有文件,如果有多个目录下则用逗号分开,如果需要在项目中分组显示,这里也要做相应的设置
s.resource_bundles = {
'PodTestLibrary' => ['Pod/Assets/*.png']
} #资源文件地址
s.public_header_files = 'Pod/Classes/**/*.h' #公开头文件地址
s.frameworks = 'UIKit' #所需的framework,多个用逗号隔开
s.dependency 'AFNetworking', '~> 2.3' #依赖关系,该项目所依赖的其他库,如果有多个需要填写多个s.dependency
end
实现步骤
创建私有podspec
包括下面几个步骤:
- 创建并设置一个私有的
Spec Repo
; - 创建
Pod
所需要的项目工程文件,并且有访问的项目版本控制地址; - 创建
Pod
对应的podsepc
文件; - 本地测试
podspec
文件是否可用; - 向私有
Spec Repo
中提交podspec; - 新建测试项目并且在
Podfile
中增加刚刚制作好的pod
并使用; - 更新维护
podspec
;
在这一系列的操作中需要创建两个私有Git
仓库,一个作为私有索引表的版本管理仓库,一个作为podspec
所关联的项目工程文件的版本管理仓库。
1. 创建私有Spec Repo
我们需要创建一个类似于master
的私有Spec Repo
, 我们可以Fork
官方的Repo
,也可以自己创建。由于我们只想添加自己的Pods
,没有必要把现有的所有公开的Pods
都Copy
一份。所以创建一个Git仓库
,这个仓库可以是私有的也可以是公开的,不过由于我们是要创建一个私有的Spec Repo
,还是创建私有的仓库吧。需要注意的是,如果项目中有其他人员共同开发的话,需要给他这个Git仓库��
的权限。至于Git仓库
托管在那个服务商下,这个可以根据每个人的不同情况来决定。
Remote端仓库
创建完成后,在Terminal
执行如下命令:
# pod repo add [Private Repo Name] [GitHub HTTPS clone URL]
$ pod repo add Test https://coding.net/wtlucky/WTSpecs.git
如果成功的话,进入 ~/.cocoapods/repos
目录下,就可以看到Test
这个目录了。
至此,私有Spec Repo创建成功。
PS:如果有其他合作人员共同使用这个私有Spec Repo
的话在他有对应Git仓库
的权限的前提下执行相同的命令添加这个Spec Repo
即可。
2. 创建Pod项目工程
这一步的实质就是创建一个包含我们需要提取的组件功能的一个Demo工程。
如果现在已经有组件项目,并且在Git版本管理下,那么这一步可以跳过了。
如果组建还在庞大的项目中没有拆分出来,需要从零开始创建一个组件库的话,我建议使用Cocoapods
提供的一个工具Using Pod Lib Create来完成第2步和第3步。
现在来介绍下这个工具的使用,在Terminal
中cd
到要创建项目的目录然后执行
$ pod lib create podTestLibrary
之后它会问你一些问题,你根据自己的需求来决定怎么回答,根据提示信息就可以了。问完问题后它回自动执行 pod install命令来创建项目并生成依赖。
生成之后的文件目录如下:
$ tree PodTestLibrary -L 2
PodTestLibrary
├── Example #demo APP
│ ├── PodTestLibrary
│ ├── PodTestLibrary.xcodeproj
│ ├── PodTestLibrary.xcworkspace
│ ├── Podfile #demo APP 的依赖描述文件
│ ├── Podfile.lock
│ ├── Pods #demo APP 的依赖文件
│ └── Tests
├── LICENSE #开源协议 默认MIT
├── Pod #组件的目录
│ ├── Assets #资源文件
│ └── Classes #类文件
├── PodTestLibrary.podspec #第三步要创建的podspec文件
└── README.md #markdown格式的README
9 directories, 5 files
接下来向项目中添加库文件和资源,运行项目并测试,保证我们需要的所有功能都成功实现。为了后续步骤可以顺利通过,建议清除库文件中所有的警告信息。
3. 创建podspec文件
通过Cocoapods
创建出来的目录本身就在本地的Git
管理下,我们需要做的是把他推送到远端仓库并打一个Tag,这是Git
操作部分的内容,这里就不再叙述了。
做完这些就可以开始编辑podspec
文件了,它是一个Ruby
文件,把编辑器的格式改为Ruby
就可以看到语法高亮,具体文件的各属性含义在上文中有说明。
编辑完podspec
文件后要用验证这个文件是否可以使用。如果有任何的WARNING
和ERROR
都是不可以的,不过Xcode
中的WARNING
是可以存在的,验证需要在Ternimal
中cd
到podspec
文件所在目录执行一个命令:
$ pod lib lint
当你看到
-> PodTestLibrary (0.1.0)
PodTestLibrary passed validation.
时,说明验证通过了,但是这只是podspec
文件是合法的,不一定说明这个pod
是可用的, 我们需要在本地做一下验证,这个就是第4步的内容了。
在验证podspec
文件是否合法的时候,如果遇到报错,可以通过命令:
$ pod lib lint --verbose
查看详细信息,如果有ERROR
,可以通过信息中的[NOTE]
提示来解决问题,如果有WARNING
并且无法清除,可以通过添加命令参数来忽略WARNING
:
$ pod lib lint --verbose --allow-warning
检查并修改库文件和podspec
直到验证通过。
4. 本地测试podspec文件是否可用
我们可以创建一个新的项目,在这个项目的Podfile
文件中直接指定刚才创建好的podspec
文件,看是否可以使用。在Podfile
中编辑有2种方式:
pod 'PodTestLibrary', :path => '~/code/Cocoapods/podTest/PodTestLibrary' # 指定路径
pod 'PodTestLibrary', :podspec => '~/code/Cocoapods/podTest/PodTestLibrary/PodTestLibrary.podspec' # 指定podspec文件
然后执行pod install
命令安装依赖,打开项目工程,可以看到库文件都被加载到Pods
子项目中了,不过它们并没有在Pods
目录下,而是跟测试项目一样存在于Development Pods/PodTestLibrary
中,这是因为我们是在本地测试,而没有把podspec
文件添加到Spec Repo
中的缘故。
在项目中编写代码,测试库文件无误后就可以开始下一步了,提交podspec
到Spec Repo
中。
5. 向私有Spec Repo中提交podspec
向Spec Repo
提交podspec
需要完成两点一个是podspec
必须通过验证无误,在一个就是删掉无用的注释(这个不是必须的,为了规范还是删掉吧)。 向我们的私有Spec Repo
提交podspec
只需要一个命令
$ pod repo push Test PodTestLibrary.podspec #前面是本地Repo名字 后面是podspec名字
如果执行失败,同样可以通过
$ pod repo push Test PodTestLibrary.podspec --verbose
查看详细信息和通过
$ pod repo push Test PodTestLibrary.podspec --allow-warning
忽略警告。完成之后这个组件库就添加到我们的私有库Test
中了,可以进入文件目录~/.cocapods/repos/Test
目录下查看。
├── LICENSE
├── PodTestLibrary
│ └── 0.1.0
│ └── PodTestLibrary.podspec
└── README.md
再去我们的Remote端
仓库,也有了一次提交,这个podspec
也已经被Push
上去了。
至此,我们已经制作好了私有组件库,使用pod search
查找新添加的库。
这里介绍的是添加到私有Repo中,如果需要添加到Cocoapods
的官方库中,则可以使用Trunk工具,具体可以查看官方文档。
6. 新建测试项目并且在Podfile中增加刚刚制作好的pod并使用
该步骤和第4步中的本地测试流程一致, 但是在Podfile
中通过正常的公共Pod
库的添加方式来添加我们的私有Pod
。
7. 更新维护podspec
现在我们已经成功创建了一个podspec
了,剩下的工作就是更新维护了,更新维护涉及到添加新版本和删除pod
。
我已经制作好了PodTestLibrary
的0.1.0
版本,现在我对他进行升级工作,这次我添加了更多的模块到PodTestLibrary
之中,包括工具类,底层Model
及UIKit
扩展等,这里又尝试了一下subspec
功能,给PodTestLibrary
创建了多个子分支。
具体做法是先将源文件添加到Pod/Classes
中,然后按照不同的模块对文件目录进行整理,因为我有四个模块,所以在Pod/Classes
下有创建了四个子目录,完成之后继续编辑之前的PodTestLibrary.podspec
,这次增加了subspec
特性
Pod::Spec.new do |s|
s.name = "PodTestLibrary"
s.version = "1.0.0"
s.summary = "Just Testing."
s.description = <<-DESC
Testing Private Podspec.
* Markdown format.
* Don't worry about the indent, we strip it!
DESC
s.homepage = "https://coding.net/u/wtlucky/p/podTestLibrary"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
s.license = 'MIT'
s.author = { "wtlucky" => "wtlucky@foxmail.com" }
s.source = { :git => "https://coding.net/wtlucky/podTestLibrary.git", :tag => "1.0.0" }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.platform = :ios, '7.0'
s.requires_arc = true
#s.source_files = 'Pod/Classes/**/*'
#s.resource_bundles = {
# 'PodTestLibrary' => ['Pod/Assets/*.png']
#}
#s.public_header_files = 'Pod/Classes/**/*.h'
s.subspec 'NetWorkEngine' do |networkEngine|
networkEngine.source_files = 'Pod/Classes/NetworkEngine/**/*'
networkEngine.public_header_files = 'Pod/Classes/NetworkEngine/**/*.h'
networkEngine.dependency 'AFNetworking', '~> 2.3'
end
s.subspec 'DataModel' do |dataModel|
dataModel.source_files = 'Pod/Classes/DataModel/**/*'
dataModel.public_header_files = 'Pod/Classes/DataModel/**/*.h'
end
s.subspec 'CommonTools' do |commonTools|
commonTools.source_files = 'Pod/Classes/CommonTools/**/*'
commonTools.public_header_files = 'Pod/Classes/CommonTools/**/*.h'
commonTools.dependency 'OpenUDID', '~> 1.0.0'
end
s.subspec 'UIKitAddition' do |ui|
ui.source_files = 'Pod/Classes/UIKitAddition/**/*'
ui.public_header_files = 'Pod/Classes/UIKitAddition/**/*.h'
ui.resource = "Pod/Assets/MLSUIKitResource.bundle"
ui.dependency 'PodTestLibrary/CommonTools'
end
s.frameworks = 'UIKit'
#s.dependency 'AFNetworking', '~> 2.3'
#s.dependency 'OpenUDID', '~> 1.0.0'
end
因为我们创建了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 Test
如果我们要删除私有Spec Repo
下的某一个podspec
怎么操作呢,此时无需借助Cocoapods
,只需要到~/.cocoapods/repos/Test
目录下,删掉库目录, 然后再将Git的变动推送到Remote仓库
即可
以上就是创建私有Pod的全部内容。
参考资料
使用Cocoapods创建私有podspec
Private Pods
Creating a Private Cocoapod
Developing Private In-House Libraries with CocoaPods
网友评论