1、创建私有Spec Repo
Spec Repo是什么?它是所有的Pods的一个索引,就是一个容器,所有公开的Pods都在这个里面,它实际是一个Git仓库remote端在GitHub上,所以想要创建pod私有库,需要创建类似于master的私有Spec Repo,先在远程仓库创建一个工程SGTSpecs,然后执行创建私有Spec Repo命令:
#pod repo add [Private Repo Name][GitHub HTTPS clone URL]
$ pod repo add SGTSpecs https://github.com/Tony-iOS-Personal/SGTSpecs.git
完成本地私有库的创建,并连接到远程仓库
完成之后,进入到~/.cocoapods/repos目录下就可以看到SGTSpecs这个目录了。
2、创建Pod项目工程文件
从零开始创建一个组件库,可以使用Cocoapods提供的工具Using Pod Lib Create ,先cd到要创建项目的目录然后执行
$ pod lib create SGTToolSDK
然后显示六个问题,1.选择一个平台( iOS / macOS);2.选择你想用的语言( Swift/ ObjC );3.是否包含一个演示应用程序;4.需要使用哪些测试框架( Specta / Kiwi / None);5.是否需要基于视图的测试;6.类前缀。 6个问题的具体介绍可以去看官方文档。回答完6个问题他会自动执行pod install命令创建项目并生成依赖,项目结构如下:
SGTToolSDK
├── Example #demo APP
│ ├──SGTToolSDK
│ ├── SGTToolSDK.xcodeproj
│ ├── SGTToolSDK.xcworkspace
│ ├── Podfile #demo APP 的依赖描述文件
│ ├── Podfile.lock
│ ├── Pods #demo APP 的依赖文件
│ └── Tests
├── LICENSE #开源协议 默认MIT
├── Pod #组件的目录
│ ├── Assets #资源文件
│ └── Classes #类文件
├── SGTToolSDK.podspec #第三步要创建的podspec文件
└── README.md #markdown格式的README
3、创建私有库pod组件
所需要做的工作就是在相应的 Pods/Developemnt Pods/ 组件 /Classes 下编码,就是向Development Pods文件夹中添加库文件和资源,将编写的组件相关的class放入SGTToolSDK/Classes中、资源图片文件放入SGTToolSDK/Assets中,并配置podspec文件,然后进入Example文件夹执行pod install命令,再打开项目工程可以看到,刚刚添加的组件已经在Pods子工程下Development Pods/SGTToolSDK中了。
pod会把添加的资源文件编译成bundle,所以引用资源文件的写法:
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *bundleURL = [bundle URLForResource:@"SGTToolSDK" withExtension:@"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithURL: bundleURL];
UIImage *img = [UIImage imageNamed:@"you imageName" inBundle:resourceBundle compatibleWithTraitCollection:nil];
4、编辑podspec文件
创建好的 .podspec 包含大量的注释说明了每个参数的含义及用法。如果想详细了解可以仔细阅读。这里只介绍几个常用的。
1、后缀为.podspec文件
该文件为Pods依赖库的描述文件,每个Pods依赖库必须有且仅有那么一个描述文件。文件名称要和我们想创建的依赖库名称保持一致,我的SGTToolSDK依赖库对应的文件名为SGTToolSDK.podspec。
1.1 podspec文件内容
SGTToolSDK.podspec的保存内容为:
Pod::Spec.newdo|s|
s.name ='SGTToolSDK'
s.version ='0.1.0'
s.summary ='A short description of SGTToolSDK.'
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage ='https://github.com/Tony-iOS-Personal/SGTToolSDK.git'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type =>'MIT', :file =>'LICENSE'}
s.author = {'sgt' => 'shaoguangtao@zhujia360.com' }
s.source = { :git =>'https://github.com/Tony-iOS-Personal/SGTToolSDK.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/'
s.ios.deployment_target ='8.0'
s.source_files ='SGTToolSDK/Classes/**/*'
# s.resource_bundles = {
# 'SGTToolSDK' => ['SGTToolSDK/Assets/*.png']
# }
s.public_header_files ='SGTToolSDK/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
end
2.其中需要说明的又几个参数:
s.name:名称,pod search 搜索的关键词
s.version:版本
s.summary:简介,pod search 搜索的关键词
s.homepage:主页地址,例如Github地址
s.license:许可证
s.author:作者
s.social_media_url:社交网址
s.platform:平台
s.source:Git仓库地址,例如在Github地址后边加上 .git 就是Git仓库地址,常见写法如下
s.source_files:需要包含的源文件,常见的写法如下
s.resources:需要包含的图片等资源文件
s.dependency:依赖库,不能依赖未发布的库
s.dependency:依赖库,如有多个可以这样写
s.requires_arc:是否要求ARC
s.source_files 常见写法
"Directory1/*" 表示匹配所有文件
"Directory1/Directory2/*.{h,m}" 表示匹配所有以.h和.m结尾的文件
"Directory1/**/*.h" 表示匹配所有子目录
s.source 常见写法
s.source = { :git => "https://github.com/Tony-iOS-Personal/SGTToolSDK.git", :commit => "68defea" }
s.source = { :git => "https://github.com/Tony-iOS-Personal/SGTToolSDK.git", :tag => 0.1.0 }
s.source = { :git => "https://github.com/Tony-iOS-Personal/SGTToolSDK.git", :tag => s.version }
commit => "68defea" 表示将这个Pod版本与Git仓库中某个commit绑定
tag => 0.1.0 表示将这个Pod版本与Git仓库中某个版本的comit绑定
tag => s.version 表示将这个Pod版本与Git仓库中相同版本的comit绑定
按照上述规则编辑完成就制作好了 .podspec。
5、验证仓库
执行以下命令,为 Pod 添加版本号,并打上 tag:
set the new version to 0.1.0
set the new tag to 0.1.0
编辑好后最好先验证 .podspec 是否有有效
$ pod spec lint
验证过程中:
->SGTToolSDK
验证成功后:SGTToolSDK.podspec passed validation.
验证失败后:[!] The spec did not pass validation, due to 1 error.
验证 .podspec 会先测试本地 .podspec 文件是否存在语法错误。测试成功再根据 .podspec 文件找到远端仓库对应的版本克隆到本地并进行配置。最后测试文件是否能够编译成功。
.podspec验证失败错误排查
语法错误
如果是因为语法错误,验证失败后会给出错误的准确定位
[!] Invalid `SGTToolSDK.podspec` file: no .floating literal anymore; put 0 before dot
s.version = “0.1.0”
^
SGTToolSDK.podspec:5: syntax error, unexpected tFLOAT, expecting '('
s.version = “0.1.0”
^
标记“^”的地方即为有语法错误的地方。
上述错误是因为使用“文本编辑”进行编辑造成的。使用文本编辑有时候英文""引号会自动变成中文“”引号。
[!] Your Podfile has had smart quotes sanitised. To avoid issues in the future, you should not use TextEdit for editing it. If you are not using TextEdit, you should turn off smart quotes in your editor of choice.
使用 vim 将其改为英文的""引号即可。
依赖错误
但是,有些非语法错误是不会给出错误原因的。这个时候可以使用“--verbose”来查看详细的验证过程来帮助定位错误。
pod spec lint SGTToolSDK.podspec --verbose
如下错误通过 --verbose 就可以找到原因。
-> SGTToolSDK(0.1.0)
- ERROR | [iOS] Encountered an unknown error (The 'Pods' target has transitive dependencies that include static binaries: (/private/var/folders/jz/b_m3k7ln47524cm__h3__mk00000gn/T/CocoaPods/Lint/Pods/BPushSDK/LibBPush/libBPush.a)) during validation.
这个错误是因为依赖库(s.dependency)包含了.a静态库造成的。虽然这并不影响Pod的使用,但是验证是无法通过的。可以通过 --use-libraries 来让验证通过。
pod spec lint SGTToolSDK.podspec --verbose --use-libraries
这种情况下使用 --use-libraries 虽然不会出现错误(error),但是有时候会带来一些警告(waring),警告同样是无法通过验证的。这时可以用 --allow-warnings 来允许警告。
pod spec lint SGTToolSDK.podspec --verbose --use-libraries --allow-warnings
安装错误
如果在其他项目 pod install 的过程中,出现包含“undefined method end_with?' for nil”字样的报错。进入“~/.cocoapods/repos”目录,删除“master”,并将 master-1 改为 master 即可。
如果出现如下错误,而你的验证可以通过,那么一般更新下版本号就可以解决。[!] Unable to find a specification for 'SGTToolSDK'.`
再次验证
如果错误发生在 .podspec 中。当修改完时,不需要再次提交就可以直接验证。如果错误发生在代码中,则需要再次提交才能验证。
6、上传代码到Git
将包含配置好的 .podspec 的项目提交 Git,并给这次提交打上 tag,可以使用SourceTree处理.
$ git add -A && git commit -m "Release 0.1.0"
$ git tag '0.1.0'
$ git push --tags
$ git push origin master
7、发布到CocoaPods
没有自身的WARNING或者ERROR之后,就可以再次提交到Spec Repo中,命令如下:
$ pod repo push SGTSpecs SGTToolSDK.podspec --allow-warnings --use-libraries
之后到~/.cocoapods/repos/SGTSpecs目录下查看,也使用pod search命令查看自己库:
-> SGTToolSDK (0.1.0)
A short description of SGTToolSDK.
pod 'SGTToolSDK', '~> 0.1.0'
- Homepage: https://github.com/Tony-iOS-Personal/SGTToolSDK.git
- Source: https://github.com/Tony-iOS-Personal/SGTToolSDK.git
- Versions: 0.1.0 [SGTSpecs repo]
(END)
这里特别强调一下,如果 s.dependency 中依赖的是 pod 私有库的话,验证和提交命令都需要指定 source :
$ pod lib lint --sources=https://github.com/Tony-iOS-Personal/SGTSpecs.git,https://github.com/CocoaPods/Specs.git --allow-warnings --no-clean --use-libraries
$ pod repo push SGTSpecs SGTToolSDK.podspec --sources=https://github.com/Tony-iOS-Personal/SGTSpecs.git,https://github.com/CocoaPods/Specs.git --allow-warnings --no-clean --use-libraries
8、项目中导入pod私有库组件
当你执行 pod install 的时候,CocoaPods 默认只会在master下搜索,而我们的spec是存在我们私有的SGTSpecs目录下的,所以需要在Podfile中指定搜索路径,在文件顶部中如下两行代码:
$ source "https://github.com/CocoaPods/Specs.git" #官方仓库地址
$ source "https://github.com/Tony-iOS-Personal/SGTSpecs.git" #私有仓库地址
在指定pod的私有库组件时有一个坑,如pod ‘YXBase’, ‘~> a.b.1’,cocoaPods实际pod组件的版本为a.b.x(x为当前版本库中最大值)。但如何pod指定版本,这就需要修改Podfile.lock文件中PODS:YXBase的版本号和Podfile文件中YXBase版本号一致