一. cocoapods內(nèi)在原理
還記得我們用cocoapods創(chuàng)建的podfile文件第一行有這一行
source 'https://github.com/CocoaPods/Specs.git'
然后我們想用某個(gè)第三方的時(shí)候是這樣寫的
pod 'AFNetworking', '~> 0.1.0'
那第一行是個(gè)什么地址呢?
請進(jìn)入你如下路徑
~/.cocoapods/repo
是否有看到一個(gè)master文件夾,以及cocoapods1.8.0之后會(huì)多一個(gè)trunk文件夾,這個(gè)是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上的一個(gè)倉庫,而trunk是cdn,cdn這個(gè)暫時(shí)不過多說明,目的就是為了加快我們pod install/update的速度。而master對應(yīng)的url就是github上的一個(gè)倉庫,這個(gè)倉庫存放的就是個(gè)人發(fā)的自己寫的第三方庫(如AFNetworking等我們經(jīng)常用的三方)的podspec文件,此文件應(yīng)該不陌生,就是個(gè)人上傳時(shí)候包含代碼各種信息,代碼存儲(chǔ)地址的那個(gè)文件,如下
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的原理吧:
定義幾個(gè)別名先。
Cocoapods source 對應(yīng) https://github.com/CocoaPods/Specs.git
AFNetworking source 對應(yīng) https://github.com/AFNetworking/AFNetworking
Cocoapods source 這個(gè)地址是個(gè)公共倉庫,里邊存儲(chǔ)各個(gè)第三方的podspec文件,這個(gè)podspec文件中記錄有各自第三方庫的倉庫地址;
比如我們用的AFNetworking,他在github上倉庫地址是這個(gè)AFNetworking source,其中包含對應(yīng)的podspec文件,這個(gè)文件中有存儲(chǔ)AFNetworking source這個(gè)地址,并且Cocoapods source 中有存儲(chǔ)有這個(gè)文件,那么當(dāng)我們在使用的時(shí)候直接用
pod 'AFNetworking', '~> 0.1.0'的時(shí)候,cocoapods會(huì)去Cocoapods source 中查找AFNetworking對應(yīng)的podspec文件,找到后從中取出AFNetworking source這個(gè)地址,然后里邊就是我們要的第三方庫的源碼了,至于后續(xù)怎么處理那就是后話了?,F(xiàn)在只是在討論cocoapods的原理,即怎么通過一個(gè)第三方的名字去找對應(yīng)的源碼。
看如下圖的展示


二. cocoapods私有倉庫
剛才說的都是cocoapods上的公共倉庫,大家知道名字就能用,那如何搞自己的私有倉庫呢?就是還是以pod的方式使用,但是只有自己能用,別人用不了,除非你給授權(quán)。
其實(shí)吧,私有倉庫和公共倉庫操作是一樣的,只是創(chuàng)建倉庫的時(shí)候你選擇的是私有還是公共而已。
2.1 先來一步一步創(chuàng)建自己的私有倉庫
首先在代碼托管平臺(tái)創(chuàng)建一個(gè)私有倉庫,我是選擇碼云,如圖

創(chuàng)建好之后會(huì)生成一個(gè)倉庫地址,類似這樣的https://gitee.com/xxx/MyProjectBase,記著這個(gè)地址,后邊會(huì)用到。
2.2 本地快速創(chuàng)建模板測試工程
快速創(chuàng)建模板測試工程,如在/Users/用戶/Desktop/路徑下創(chuàng)建CocoaPodRemoteLib目錄,然后終端輸入
cd /Users/Funky/Desktop/CocoaPodRemoteLib
pod lib create MyProjectBase
此時(shí)會(huì)有一些具體的選項(xiàng),選擇一下即可,如圖

填寫以上信息后Xcode會(huì)自動(dòng)打開測試工程,在測試模板工程文件夾下,我們可以看到如下:

假如我們要?jiǎng)?chuàng)建的第三方是個(gè)Category,則用Category去替換Replace.m文件,在回到Example路徑下,重新執(zhí)行pod install操作,即在終端輸入
cd /Users/用戶/Desktop/CocoaPodRemoteLib/MyProjectBase/Example
pod install
此時(shí)打開模板測試工程,我們可以看到Pods > Development Pods > MyProjectBase > MyProjectBase > Classes > Category > (.h .m)
我們可以在模板測試工程中進(jìn)行修改和操作!
2.3 將上面的模板測試工程,提交到第四步創(chuàng)建的遠(yuǎn)程代碼倉庫
在終端輸入如下命令
cd /Users/用戶/Desktop/CocoaPodRemoteLib/MyProjectBase
git status
git add .
git commit -m'基礎(chǔ)組件測試工程'
編輯MyProjectBase 模版工程的MyProjectBase.podspec文件

編輯完之后在終端輸入此命令(驗(yàn)證上一步編輯的 MyProjectBase.podspec文件)
pod lib lint
如果有ERROR,則需要去一個(gè)個(gè)修改完成,例如某個(gè)Category的.m文件沒有正確的引入依賴庫等都會(huì)造成ERROR,解決好所有的ERROR后,驗(yàn)證結(jié)果如下:

git status
git add .
git commit -m '編輯spec文件'
這是一個(gè)警告,目前也并沒有找到合適的解決辦法,我們添加 --allow-warnings進(jìn)行忽略
pod lib lint --allow-warnings
此時(shí) MyProjectBase passed validation. 則說明驗(yàn)證通過
將本地庫與遠(yuǎn)程代碼倉庫進(jìn)行關(guān)聯(lián)
git remote add origin (2.1中生成的碼云倉庫地址)
git push origin master (提交到遠(yuǎn)程倉庫)
git tag '0.1.0' (要與MyProjectBase.podspec文件中的tag值保持一致)
git push --tags(將tag提交到遠(yuǎn)程)
pod spec lint --allow-warnings(驗(yàn)證遠(yuǎn)程是否正確)
提示MyProjectBase.podspec passed validation表明驗(yàn)證通過。
此時(shí)私有庫已經(jīng)可以通過pod來管理使用了,只是不能用通常的pod引入方式
現(xiàn)在我們想用此私有倉庫在podfile中這樣寫
pod 'MyProjectBase', :git =>'https://gitee.com/xxx/MyProjectBase.git'
然后終端執(zhí)行pod install即可。
但是有個(gè)問題,為什么不能直接用名字,不加后邊的git地址呢?
其實(shí)想象一下最開始cocoapods的原理,pod通過名字去pod倉庫中找到對應(yīng)名字的podspec文件,然后在podspec文件中找到代碼。
而我們此時(shí)的私有倉庫如果不加后邊的git地址的話,根本沒辦法找到對應(yīng)代碼。那么如果想用正常的方式用這個(gè)私有倉庫就需要把私有庫的podspec放一個(gè)類似官方master文件夾的地方。下邊就開始著手做這個(gè)工作。
三. 創(chuàng)建私有倉庫的索引倉庫
因?yàn)楣俜骄陀幸粋€(gè)索引倉庫,然后通過索引倉庫來管理第三方庫,那么我們也可以仿照官方的做法,自己見一個(gè)私有的索引倉庫
3.1 新建私有索引倉庫
**在碼云上創(chuàng)建一個(gè)自己的遠(yuǎn)程私有索引庫,用來存放私有框架的詳細(xì)描述信息,即podspec文件

創(chuàng)建好后也會(huì)生成一個(gè)git倉庫的地址https://,然后在終端輸入此命令添加本地私有索引庫并管理對應(yīng)的遠(yuǎn)程私有庫地址
pod repo add MyProjectSpec https://gitee.com/xxx/MyProjectSpec.git
再次查看本地已存在的索引庫 $ pod repo

此時(shí)我們的私有索引庫已將創(chuàng)建完成,類似官方的master目錄,那么接下來就是把我們之前創(chuàng)建的私有庫的podspec文件上傳到我們的私有索引庫中即可。
3.2 上傳私有庫podspec文件到私有索引庫
進(jìn)入我們的私有庫目錄,然后終端輸入
pod repo push MyProjectSpec MyProjectBase.podspec

表示提交成功,此時(shí)遠(yuǎn)程私有庫到此就已結(jié)束
注意:提交后,依然會(huì)驗(yàn)證 podspec文件,驗(yàn)證通過后 會(huì)自動(dòng)上傳到在遠(yuǎn)程spec索引庫,不信的話你可以看看在第二步創(chuàng)建的Spec遠(yuǎn)程私有索引庫,是不是多了一個(gè)MyProjectBase/ 0.1.0文件.
到此為止,我們自己的私有庫已經(jīng)全部搞定,下邊我們就可以正常的使用了,如下
pod 'MyProjectBase'
但是這樣還不行,因?yàn)閜od默認(rèn)會(huì)去官方的索引庫,即master中找這個(gè)庫,但是我們這個(gè)是私有庫,怎么可能在官方的索引庫中,此時(shí)就要像文章最開始那樣,把我們自己私有的索引庫地址給加上,即在podfile開頭,加上
source 'https://gitee.com/xxx/MyProjectSpec.git'
pod install即可在工程中的pod目錄中看到我們自己的私有庫了。
四. 私有庫修改后的操作
如下圖:

在本地的基礎(chǔ)組件的Classes路徑下 又新增了兩個(gè)文件夾(Base,Tool)
$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyProjectBase
編輯MyProjectBase 模版工程的MyProjectBase.podspec文件

$ git status
$ git add .
$ git commit -m'新增Base,Tool文件內(nèi)容'
$ git push origin master (提交到遠(yuǎn)程)
$ git tag '0.2.0'
$ git push --tags
$ pod repo push MyProjectSpec MyProjectBase.podspec (如果沒有私有庫索引倉庫,不需要在push到索引庫)
$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyMainProject
修改Podfile文件

$ pod install即可
五. 私有庫分拆子庫
在基礎(chǔ)組件MyProjectBase內(nèi)部生成子庫
問題描述:當(dāng)我們執(zhí)行完第九步后,我們發(fā)現(xiàn)主工程的Pods中并沒有按文件夾(Base,Category,Tool)進(jìn)行不同類的劃分,同時(shí)當(dāng)我們僅僅想引入一個(gè)Category庫時(shí),連同Base,Tool也引入進(jìn)項(xiàng)目中,這就太難受了!
參照AFNetworking

修改MyProjectBase.podspec文件

$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyProjectBase
$ git status
$ git add .
$ git commit -m'生成子庫文件夾'
$ git push origin master (提交到遠(yuǎn)程)
$ git tag '0.2.0'
$ git push --tags
$ pod repo push MyProjectSpec MyProjectBase.podspec
$ cd /Users/Funky/Desktop/CocoaPodRemoteLib/MyMainProject
修改Podfile文件

$ pod install
就現(xiàn)在 快打開主工程看一看吧!
說個(gè)有意思的東西
先看下cocoapods的索引庫master的目錄結(jié)構(gòu)

這個(gè)目錄結(jié)構(gòu)有看的懂得嗎?什么鬼全是單個(gè)數(shù)字或者字母,其實(shí)有其巧妙之處的,看前兩個(gè)三方庫的md5加密后的字符串


有發(fā)現(xiàn)什么嗎?他們加密后字符串開頭都是456,而他們在master中目錄是4文件夾-〉5文件夾-〉6文件夾。
所以cocoapods找一個(gè)三方庫的podspec文件的時(shí)候其實(shí)是先把三方的名字md5加密,然后就直接那前三位找到對應(yīng)目錄就是這個(gè)三方庫對應(yīng)的podspec文件的地址了,效率非常的高,也很巧妙。
參考:
我這篇大部分是參考這篇文章,然后在次序上做了調(diào)整,但也有很多自己的思考,畢竟自己實(shí)操過的
轉(zhuǎn)載的上述文章,怕別人刪了以后看不到??
Cocopods組件化之podspec文件解析
podspecs文件說明
官方podspec文檔
官方podfile文檔
Cocoapods驗(yàn)證podspec報(bào)錯(cuò)總結(jié)
AFNetworking的podspec文件,看看牛逼的庫怎么寫的??