Henry的博客

有理想的人,生活总是火热的

欢迎来到Henry的博客,希望与您在iOS开发领域共同交流与学习


iOS开发-使用Cocoapods创建私有podspec

Cocoapods是非常好用的一个iOS依赖管理工具,使用它可以方便的管理和更新项目中所使用到的第三方库,以及将自己的项目中的公共组件交由它去管理。制作共有podSpec可以参考我博客园里另一篇文章上传代码到cocoapod ,自己的框架提供给开发者使用。其实共有和私有的区别就在于对podSpec的管理,这里整体先说明一下创建一个私有的podspec包括如下那么几个步骤:

1
2
3
4
5
6
7
创建并设置一个私有的Spec Repo。
创建Pod的所需要的项目工程文件,并且有可访问的项目版本控制地址。
创建Pod所对应的podspec文件。
本地测试配置好的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目录的结构是这个样子的

1
2
3
4
5
.
├── Specs
└── [SPEC_NAME]
└── [VERSION]
└── [SPEC_NAME].podspec

因此我们需要创建一个类似于master的私有Spec Repo,这里我们可以fork官方的Repo,也可以自己创建,个人建议不fork,因为你只是想添加自己的Pods,没有必要把现有的公开Pods都copy一份。所以创建一个 Git仓库,这个仓库你可以创建私有的也可以创建公开的,不过既然私有的Spec Repo,还是创建私有的仓库吧,需要注意的就是如果项目中有其他同事共同开发的话,你还要给他这个Git仓库的权限。因为GitHub的私有仓库是收费的,我还不是GitHub的付费用户,所以我使用了其他Git服务,我使用的是开源中国,当然还有其他的可供选择Coding、Bitbucket以及CSDN。创建完成之后在Terminal中执行如下命令:

$ pod repo add HXSpecs https://gitee.com/null_536_3468/HXSpecs.git

此时如果成功的话进入到~/.cocoapods/repos目录下就可以看到HXSpecs这个目录了。至此第一步创建私有Spec Repo完成。

PS:上述代码只需要在第一次创建私有Spec Repo的时候用到,之后你每次创建其他私有Pod项目只需要从下面的步骤开始。如果有其他合作人员共同使用这个私有Spec Repo的话在他有对应Git仓库的权限的前提下执行相同的命令添加这个Spec Repo即可。

创建Pod项目工程文件

这一步就跟创建共有Pod项目一样了,首先要创建一个项目托管仓库,共有私有都可以,这里我们还是在开源中国上创建一个名为HRCargary的私有仓库

然后我们把项目克隆岛本地,执行命令

1
$ git clone https://gitee.com/null_536_3468/HRCargary.git

我们在刚刚克隆下来的文件夹里在创建一个名为HRCargary的文件夹,里面放着4个文件,这个文件夹就是放我们的组件的。然后再创建一个名为testDemo的文件夹,这个文件夹里放着我的的测试工程项目,如果不需要测试工程也可以不创建。现在看一下我们所克隆下来的项目的目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ tree -L 3
.
├── HRCargary
│ ├── UIColor+Extension.h
│ ├── UIColor+Extension.m
│ ├── UIImage+Extension.h
│ └── UIImage+Extension.m
├── LICENSE
├── README.md
└── testDemo
└── demo
├── demo
└── demo.xcodeproj

现在我们要把添加的文件push到远程仓库里去了,执行命令:

1
2
3
$ git add .
$ git commit -m "添加项目文件"
$ git push -u origin master

因为podspec文件中获取Git版本控制的项目还需要tag号,所以我们要打上一个tag

1
2
$ git tag '1.2.2'
$ git push --tags

创建Pod所对应的podspec文件。

打开终端定位到克隆的文件夹

1
$ cd /Users/WanYin/Desktop/hr/HRCargary

然后执行命令

1
$ pod spec create HRCargary.podspec

这是你会发现多了一个HRCargary.podspec文件,打开它是长这个样子的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Pod::Spec.new do |s|
#名称
s.name = "HRCargary"
#版本号
s.version = "1.2.2"
#简短介绍,下面是详细介绍
s.summary = "NSString&UIImage的分类"
s.description = <<-DESC
好用的分类哈哈哈哈哈哈哈哈哈哈哈哈哈哈
DESC
#主页,这里要填写可以访问到的地址,不然验证不通过
s.homepage = "https://gitee.com/null_536_3468/HRCargary"
#开源协议
s.license = "MIT"
#作者信息
s.author = { "Henry" => "382782411@qq.com" }
#支持的平台及版本
s.platform = :ios, "8.0"
#项目地址,这里不支持ssh的地址,验证不通过,只支持HTTP和HTTPS,最好使用HTTPS
s.source = { :git => "https://gitee.com/null_536_3468/HRCargary.git", :tag => "#{s.version}" }
#代码源文件地址,**/*表示Classes目录及其子目录下所有文件,如果有多个目录下则用逗号分开,如果需要在项目中分组显示,这里也要做相应的设置
s.source_files = "HRCargary/**/*"
#资源文件地址,没有可以不写
s.resources = ["testDemo/demo/demo/*.xib","testDemo/demo/demo/*.xcassets"]
#是否使用ARC
s.requires_arc = true
#依赖关系,该项目所依赖的其他库,如果有多个需要填写多个s.dependency
# s.dependency "JSONKit", "~> 1.4"
end

填写完成后我们再看一下项目最终的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
.
├── HRCargary
│ ├── UIColor+Extension.h
│ ├── UIColor+Extension.m
│ ├── UIImage+Extension.h
│ └── UIImage+Extension.m
├── HRCargary.podspec
├── LICENSE
├── README.md
└── testDemo
└── demo
├── demo
└── demo.xcodeproj

本地测试配置好的podspec文件是否可用。

打开终端定位到克隆下来的文件夹后执行命令

1
$ pod spec lint ./HRCargary.podspec --allow-warnings

当你看到时,

1
2
3
4
-> HRCargary (1.2.2)
- WARN | url: The URL (https://gitee.com/null_536_3468/HRCargary) is not reachable.
Analyzed 1 podspec.
HRCargary.podspec passed validation.

说明验证通过了,不过这只是这个podspec文件是合格的。WARN可以不用管。

向私有的Spec Repo中提交podspec

向Spec Repo提交podspec需要完成两点一个是podspec必须通过验证无误,在一个就是删掉无用的注释(这个不是必须的,为了规范还是删掉吧)。 向我们的私有Spec Repo提交podspec只需要一个命令

1
pod repo push HXSpecs HRCargary.podspec #前面是本地Repo名字 后面是podspec名字

完成之后这个组件库就添加到我们的私有Spec Repo中了,可以进入到~/.cocoapods/repos/HXSpecs目录下查看

1
2
3
4
5
6
.
├── LICENSE
├── HRCargary
│ └── 1.2.2
│ └── HRCargary.podspec
└── README.md

再去看我们的Spec Repo远端仓库,也有了一次提交,这个podspec也已经被Push上去了。至此,我们的这个组件库就已经制作添加完成了,使用pod search命令就可以查到我们自己的库了

1
2
3
4
5
6
7
$ pod search HRCargary
-> HRCargary (1.2.2)
NSString&UIImage的分类
pod 'HRCargary', '~> 1.2.2'
- Homepage: https://gitee.com/null_536_3468/HRCargary
- Source: https://gitee.com/null_536_3468/HRCargary.git
- Versions: 1.2.2, 1.0.0 [master repo]

Ps:如果搜索不到给个终极解决方法:到 ~/Library/Caches/CocoaPods目录删除search_index.json然后重新搜索就有啦。

接下来我们在项目里可以这样使用私有库组件,在Podfile里增加

1
2
3
4
5
6
7
platform :ios, '8.0'
source 'https://github.com/CocoaPods/Specs.git'
#这里就是你的私有Spec Repo
source 'https://gitee.com/null_536_3468/HXSpecs.git'
target :test do
pod 'HRCargary'
end

更新维护podspec

最后再来说一下制作好的podspec文件后续的更新维护工作,比如如何添加新的版本,如何删除Pod。

我已经制作好了HRCargary的1.2.2版本,现在我对他进行升级工作,这次我添加了更多的模块到HRCargary之中,包括工具类,底层Model及UIKit扩展等,这里又尝试了一下subspec功能,给HRCargary创建了多个子分支。

具体做法是先将源文件添加到HRCargary中,然后按照不同的模块对文件目录进行整理,因为我有2个模块,所以在HRCargary下有创建了2个子目录,完成之后继续编辑之前的HRCargary.podspec,这次增加了subspec特性,先看一下HRCargary的文件目录

1
2
3
4
5
6
7
8
9
10
.
├── CommonTools
│ ├── TimeUtil.h
│ └── TimeUtil.m
└── cargary
├── HXTableViewCell.xib
├── UIColor+Extension.h
├── UIColor+Extension.m
├── UIImage+Extension.h
└── UIImage+Extension.m

编辑HRCargary.podspec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Pod::Spec.new do |s|
#名称
s.name = "HRCargary"
#版本号,要跟远程仓库里tag值一样,并且每次更新库都得改变
s.version = "2.2.2"
#简短介绍,下面是详细介绍
s.summary = "NSString&UIImage的分类"
s.description = <<-DESC
好用的分类哈哈哈哈哈哈哈哈哈哈哈哈哈哈
DESC
#主页,这里要填写可以访问到的地址,不然验证不通过
s.homepage = "https://gitee.com/null_536_3468/HRCargary"
#开源协议
s.license = "MIT"
#作者信息
s.author = { "Henry" => "382782411@qq.com" }
#支持的平台及版本
s.platform = :ios, "8.0"
#项目地址,这里不支持ssh的地址,验证不通过,只支持HTTP和HTTPS,最好使用HTTPS
s.source = { :git => "https://gitee.com/null_536_3468/HRCargary.git", :tag => "#{s.version}" }
#代码源文件地址,**/*表示Classes目录及其子目录下所有文件,如果有多个目录下则用逗号分开,如果需要在项目中分组显示,这里也要做相应的设置
#s.source_files = "HRCargary/**/*"
#资源文件地址,没有可以不写
#s.resources = ["testDemo/demo/demo/*.xib","testDemo/demo/demo/*.xcassets"]
#是否使用ARC
s.requires_arc = true
#依赖关系,该项目所依赖的其他库,如果有多个需要填写多个s.dependency
# s.dependency "JSONKit", "~> 1.4"
s.subspec 'CommonTools' do |commonTools|
commonTools.source_files = 'HRCargary/CommonTools/**/*'
commonTools.public_header_files = 'HRCargary/CommonTools/**/*.h'
end
s.subspec 'cargary' do |cargarys|
cargarys.source_files = 'HRCargary/cargary/**/*'
cargarys.public_header_files = 'HRCargary/cargary/**/*.h'
end
end

因为我们创建了subspec所以项目整体的依赖dependency,源文件source_files,头文件public_header_files,资源文件resource等都移动到了各自的subspec中,每个subspec之间也可以有相互的依赖关系。

编辑完成之后,先将个工程push到远端仓库,并打上新的tag->2.2.2。

最后再次使用$ pod spec lint ./HRCargary.podspec --allow-warnings验证编辑好的podsepc文件,没有自身的ERROR之后,就可以再次提交到Spec Repo中了,命令跟之前是一样的pod repo push HXSpecs HRCargary.podspec

完成这些之后,在实际项目中我们就可以选择使用整个组件库或者是组件库的某一个部分了,对应的Podfile中添加的内容为

1
2
3
4
5
6
7
8
9
platform :ios, '8.0'
source 'https://github.com/CocoaPods/Specs.git'
#私有Spec Repo
source 'https://gitee.com/null_536_3468/HXSpecs.git'
target :test do
pod 'HRCargary' #使用整个库
#pod 'HRCargary/CommonTools' #使用某一个部分
#pod 'HRCargary/cargary'
end

你会看到组件会以分组的形式存在,如AFNetworking一样,并不会打乱文件目录结构。

最后介绍一下如何删除一个私有Spec Repo,只需要执行一条命令即可

1
$ pod repo remove HXSpecs

这样这个Spec Repo就在本地删除了,我们还可以通过

1
$ pod repo add WTSpecs https://gitee.com/null_536_3468/HXSpecs.git

再把它给加回来。
如果我们要删除私有Spec Repo下的某一个podspec怎么操作呢,此时无需借助Cocoapods,只需要cd到~/.cocoapods/repos/HXSpecs目录下,删掉库目录$ rm -Rf HRCargary
然后在将Git的变动push到远端仓库即可

1
2
3
git add .
git commit -m "remove unuseful pods"
git push -u origin master
最近的文章

Python实践一、将网页转换为pdf电子书

本人是个”收集狂”(不要想歪了哈,我只是喜欢收藏技术贴),遇到好的东西就喜欢收藏或记录下来,尤其是好的技术文章或者工具。这里就要提到廖雪峰老师的官方网站了,廖老师写的Python、JavaScript、Git教程真心好呀,每每都要去逛逛。于是就有了今天这个需求,把廖老师的教程由网页转为PDF电子书, …

于  Python 继续阅读
更早的文章

iOS开发-RunLoop实例应用

之前看过很多有关RunLoop的文章,其中要么是主要介绍RunLoop的基本概念,要么是主要讲解RunLoop的底层原理,很少用真正的实例来讲解RunLoop的,这其中有大部分原因是由于大家在项目中很少能用到RunLoop吧。基于这种原因,本文中将用很少的篇幅来对基础内容做以介绍,然后主要利用实例来 …

于  iOS开发 继续阅读