一. cocoapods内在原理
还记得我们用cocoapods创建的podfile文件第一行有这一行
source 'https://github.com/CocoaPods/Specs.git'
然后我们想用某个第三方的时候是这样写的
pod 'AFNetworking', '~> 0.1.0'
那第一行是个什么地址呢?
请进入你如下路径
~/.cocoapods/repo
是否有看到一个master文件夹,以及cocoapods1.8.0之后会多一个trunk文件夹,这个是cocoapods把specs repo的源给切换成cdn了。
终端输入
pod repo
输出如下
master
- Type: git (master)
- URL: https://github.com/CocoaPods/Specs.git
- Path: /Users/kang/.cocoapods/repos/master
trunk
- Type: CDN
- URL: https://cdn.cocoapods.org/
- Path: /Users/kang/.cocoapods/repos/trunk
可以看到master是git上的一个仓库,而trunk是cdn,cdn这个暂时不过多说明,目的就是为了加快我们pod install/update的速度。而master对应的url就是github上的一个仓库,这个仓库存放的就是个人发的自己写的第三方库(如AFNetworking等我们经常用的三方)的podspec文件,此文件应该不陌生,就是个人上传时候包含代码各种信息,代码存储地址的那个文件,如下
Pod::Spec.new do |s|
s.name = 'XXXKit'
s.version = '0.3.0'
s.summary = 'A short description of XXXKit.'
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'https://gitee.com/kzq5/XXXKit.git'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'kang' => 'xxx@qq.com' }
s.source = { :git => 'https://gitee.com/xxx/XXXKit.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.resource_bundles = {
'XXXKit' => ['XXXKit/Assets/*.png','XXXKit/Assets/*.caf']
}
s.subspec 'Category' do |c|
c.source_files = 'XXXKit/Classes/Category/**/*'
end
s.subspec 'Utils' do |u|
u.source_files = 'XXXKit/Classes/Utils/**/*'
end
#s.source_files = 'XXXKit/Classes/**/*'
# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
end
到此,来说说cocoapods的原理吧:
定义几个别名先。
Cocoapods source 对应 https://github.com/CocoaPods/Specs.git
AFNetworking source 对应 https://github.com/AFNetworking/AFNetworking
Cocoapods source 这个地址是个公共仓库,里边存储各个第三方的podspec文件,这个podspec文件中记录有各自第三方库的仓库地址;
比如我们用的AFNetworking,他在github上仓库地址是这个AFNetworking source,其中包含对应的podspec文件,这个文件中有存储AFNetworking source这个地址,并且Cocoapods source 中有存储有这个文件,那么当我们在使用的时候直接用
pod 'AFNetworking', '~> 0.1.0'的时候,cocoapods会去Cocoapods source 中查找AFNetworking对应的podspec文件,找到后从中取出AFNetworking source这个地址,然后里边就是我们要的第三方库的源码了,至于后续怎么处理那就是后话了。现在只是在讨论cocoapods的原理,即怎么通过一个第三方的名字去找对应的源码。
看如下图的展示
Cocoapods source中存储的afnetworking库的podspec文件路径 Cocoapods source中存储的afnetworking库的podspec文件内容
二. cocoapods私有仓库
刚才说的都是cocoapods上的公共仓库,大家知道名字就能用,那如何搞自己的私有仓库呢?就是还是以pod的方式使用,但是只有自己能用,别人用不了,除非你给授权。
其实吧,私有仓库和公共仓库操作是一样的,只是创建仓库的时候你选择的是私有还是公共而已。
2.1 先来一步一步创建自己的私有仓库
首先在代码托管平台创建一个私有仓库,我是选择码云,如图
创建好之后会生成一个仓库地址,类似这样的https://gitee.com/xxx/MyProjectBase,记着这个地址,后边会用到。
2.2 本地快速创建模板测试工程
快速创建模板测试工程,如在/Users/用户/Desktop/路径下创建CocoaPodRemoteLib目录,然后终端输入
cd /Users/Funky/Desktop/CocoaPodRemoteLib
pod lib create MyProjectBase
此时会有一些具体的选项,选择一下即可,如图
图片.png
填写以上信息后Xcode会自动打开测试工程,在测试模板工程文件夹下,我们可以看到如下:
图片.png
假如我们要创建的第三方是个Category,则用Category去替换Replace.m文件,在回到Example路径下,重新执行pod install操作,即在终端输入
cd /Users/用户/Desktop/CocoaPodRemoteLib/MyProjectBase/Example
pod install
此时打开模板测试工程,我们可以看到Pods > Development Pods > MyProjectBase > MyProjectBase > Classes > Category > (.h .m)
我们可以在模板测试工程中进行修改和操作!
2.3 将上面的模板测试工程,提交到第四步创建的远程代码仓库
在终端输入如下命令
cd /Users/用户/Desktop/CocoaPodRemoteLib/MyProjectBase
git status
git add .
git commit -m'基础组件测试工程'
编辑MyProjectBase 模版工程的MyProjectBase.podspec文件
盗图,文末会有参考地址
编辑完之后在终端输入此命令(验证上一步编辑的 MyProjectBase.podspec文件)
pod lib lint
如果有ERROR,则需要去一个个修改完成,例如某个Category的.m文件没有正确的引入依赖库等都会造成ERROR,解决好所有的ERROR后,验证结果如下:
图片.png
git status
git add .
git commit -m '编辑spec文件'
这是一个警告,目前也并没有找到合适的解决办法,我们添加 --allow-warnings进行忽略
pod lib lint --allow-warnings
此时 MyProjectBase passed validation. 则说明验证通过
将本地库与远程代码仓库进行关联
git remote add origin (2.1中生成的码云仓库地址)
git push origin master (提交到远程仓库)
git tag '0.1.0' (要与MyProjectBase.podspec文件中的tag值保持一致)
git push --tags(将tag提交到远程)
pod spec lint --allow-warnings(验证远程是否正确)
提示MyProjectBase.podspec passed validation表明验证通过。
此时私有库已经可以通过pod来管理使用了,只是不能用通常的pod引入方式
现在我们想用此私有仓库在podfile中这样写
pod 'MyProjectBase', :git =>'https://gitee.com/xxx/MyProjectBase.git'
然后终端执行pod install即可。
但是有个问题,为什么不能直接用名字,不加后边的git地址呢?
其实想象一下最开始cocoapods的原理,pod通过名字去pod仓库中找到对应名字的podspec文件,然后在podspec文件中找到代码。
而我们此时的私有仓库如果不加后边的git地址的话,根本没办法找到对应代码。那么如果想用正常的方式用这个私有仓库就需要把私有库的podspec放一个类似官方master文件夹的地方。下边就开始着手做这个工作。
三. 创建私有仓库的索引仓库
因为官方就有一个索引仓库,然后通过索引仓库来管理第三方库,那么我们也可以仿照官方的做法,自己见一个私有的索引仓库
3.1 新建私有索引仓库
**在码云上创建一个自己的远程私有索引库,用来存放私有框架的详细描述信息,即podspec文件
创建好后也会生成一个git仓库的地址https://,然后在终端输入此命令添加本地私有索引库并管理对应的远程私有库地址
pod repo add MyProjectSpec https://gitee.com/xxx/MyProjectSpec.git
再次查看本地已存在的索引库 $ pod repo
图片.png
此时我们的私有索引库已将创建完成,类似官方的master目录,那么接下来就是把我们之前创建的私有库的podspec文件上传到我们的私有索引库中即可。
3.2 上传私有库podspec文件到私有索引库
进入我们的私有库目录,然后终端输入
图片.pngpod repo push MyProjectSpec MyProjectBase.podspec
表示提交成功,此时远程私有库到此就已结束
注意:提交后,依然会验证 podspec文件,验证通过后 会自动上传到在远程spec索引库,不信的话你可以看看在第二步创建的Spec远程私有索引库,是不是多了一个MyProjectBase/ 0.1.0文件.
到此为止,我们自己的私有库已经全部搞定,下边我们就可以正常的使用了,如下
pod 'MyProjectBase'
但是这样还不行,因为pod默认会去官方的索引库,即master中找这个库,但是我们这个是私有库,怎么可能在官方的索引库中,此时就要像文章最开始那样,把我们自己私有的索引库地址给加上,即在podfile开头,加上
source 'https://gitee.com/xxx/MyProjectSpec.git'
pod install即可在工程中的pod目录中看到我们自己的私有库了。
四. 私有库修改后的操作
如下图:
image在本地的基础组件的Classes路径下 又新增了两个文件夹(Base,Tool)
$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyProjectBase
编辑MyProjectBase 模版工程的MyProjectBase.podspec文件
image$ git status
$ git add .
$ git commit -m'新增Base,Tool文件内容'
$ git push origin master (提交到远程)
$ git tag '0.2.0'
$ git push --tags
$ pod repo push MyProjectSpec MyProjectBase.podspec (如果没有私有库索引仓库,不需要在push到索引库)
$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyMainProject
修改Podfile文件
image$ pod install即可
五. 私有库分拆子库
在基础组件MyProjectBase内部生成子库
问题描述:当我们执行完第九步后,我们发现主工程的Pods中并没有按文件夹(Base,Category,Tool)进行不同类的划分,同时当我们仅仅想引入一个Category库时,连同Base,Tool也引入进项目中,这就太难受了!
参照AFNetworking
image修改MyProjectBase.podspec文件
image$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyProjectBase
$ git status
$ git add .
$ git commit -m'生成子库文件夹'
$ git push origin master (提交到远程)
$ git tag '0.2.0'
$ git push --tags
$ pod repo push MyProjectSpec MyProjectBase.podspec
$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyMainProject
修改Podfile文件
image$ pod install
就现在 快打开主工程看一看吧!
说个有意思的东西
先看下cocoapods的索引库master的目录结构
图片.png
这个目录结构有看的懂得吗?什么鬼全是单个数字或者字母,其实有其巧妙之处的,看前两个三方库的md5加密后的字符串
AlamofireDomain CTHandyCategories
有发现什么吗?他们加密后字符串开头都是456,而他们在master中目录是4文件夹-〉5文件夹-〉6文件夹。
所以cocoapods找一个三方库的podspec文件的时候其实是先把三方的名字md5加密,然后就直接那前三位找到对应目录就是这个三方库对应的podspec文件的地址了,效率非常的高,也很巧妙。
参考:
我这篇大部分是参考这篇文章,然后在次序上做了调整,但也有很多自己的思考,毕竟自己实操过的
转载的上述文章,怕别人删了以后看不到😅
Cocopods组件化之podspec文件解析
podspecs文件说明
官方podspec文档
官方podfile文档
Cocoapods验证podspec报错总结
AFNetworking的podspec文件,看看牛逼的库怎么写的😄
网友评论