一. cocoapods內在原理
還記得我們用cocoapods創(chuàng)建的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上的一個倉庫,這個倉庫存放的就是個人發(fā)的自己寫的第三方庫(如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這個地址,然后里邊就是我們要的第三方庫的源碼了,至于后續(xù)怎么處理那就是后話了?,F(xiàn)在只是在討論cocoapods的原理,即怎么通過一個第三方的名字去找對應的源碼。
看如下圖的展示


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

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

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

假如我們要創(chuàng)建的第三方是個Category,則用Category去替換Replace.m文件,在回到Example路徑下,重新執(zhí)行pod install操作,即在終端輸入
cd /Users/用戶/Desktop/CocoaPodRemoteLib/MyProjectBase/Example
pod install
此時打開模板測試工程,我們可以看到Pods > Development Pods > MyProjectBase > MyProjectBase > Classes > Category > (.h .m)
我們可以在模板測試工程中進行修改和操作!
2.3 將上面的模板測試工程,提交到第四步創(chuàng)建的遠程代碼倉庫
在終端輸入如下命令
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后,驗證結果如下:

git status
git add .
git commit -m '編輯spec文件'
這是一個警告,目前也并沒有找到合適的解決辦法,我們添加 --allow-warnings進行忽略
pod lib lint --allow-warnings
此時 MyProjectBase passed validation. 則說明驗證通過
將本地庫與遠程代碼倉庫進行關聯(lián)
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引入方式
現(xiàn)在我們想用此私有倉庫在podfile中這樣寫
pod 'MyProjectBase', :git =>'https://gitee.com/xxx/MyProjectBase.git'
然后終端執(zhí)行pod install即可。
但是有個問題,為什么不能直接用名字,不加后邊的git地址呢?
其實想象一下最開始cocoapods的原理,pod通過名字去pod倉庫中找到對應名字的podspec文件,然后在podspec文件中找到代碼。
而我們此時的私有倉庫如果不加后邊的git地址的話,根本沒辦法找到對應代碼。那么如果想用正常的方式用這個私有倉庫就需要把私有庫的podspec放一個類似官方master文件夾的地方。下邊就開始著手做這個工作。
三. 創(chuàng)建私有倉庫的索引倉庫
因為官方就有一個索引倉庫,然后通過索引倉庫來管理第三方庫,那么我們也可以仿照官方的做法,自己見一個私有的索引倉庫
3.1 新建私有索引倉庫
**在碼云上創(chuàng)建一個自己的遠程私有索引庫,用來存放私有框架的詳細描述信息,即podspec文件

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

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

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

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

$ 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文件

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

修改MyProjectBase.podspec文件

$ 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文件

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

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


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