Cocoapods是非常好用的一個iOS依賴管理工具,使用它可以方便的管理和更新項目中所使用到的第三方庫,以及將自己的項目中的公共組件交由它去管理。Cocoapods的介紹及優點本文就不在贅述,我開始使用Cocoapods還是在兩年前,那個時候它剛剛出現,網上的資料還非常的少,就連他們自己的HomePage都十分的簡單,我就著手嘗試著使用了一下,用它管理起第三方庫確實是十分的方便順手。後來它有了更強大的功能就是自己創建podspec,更可以設置私有的庫。
春節回來上班,沒有什麼任務做,正好項目中有一些公共組件需要從龐大的項目體系中剝離出來,而且年前項目終於從SVN遷移到了Git,真是喜大普奔,大快人心!這樣項目使用Cocoapods就有了條件,正好趁著這兩天沒有什麼事情做,學習一下創建私有的podspec並在項目中部署使用,以及pods的subspec的創建及使用。
整體先說明一下創建一個私有的podspec包括如下那麼幾個步驟:
創建並設置一個私有的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目錄的結構是這個樣子的
. ├── 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 Code.
創建完成之後在Terminal中執行如下命令
# pod repo add [Private Repo Name] [GitHub HTTPS clone URL] $ pod repo add WTSpecs https://coding.net/wtlucky/WTSpecs.git
此時如果成功的話進入到~/.cocoapods/repos目錄下就可以看到WTSpecs這個目錄了。至此第一步創建私有Spec Repo完成。
PS:如果有其他合作人員共同使用這個私有Spec Repo的話在他有對應Git倉庫的權限的前提下執行相同的命令添加這個Spec Repo即可。
創建Pod項目工程文件
這個第二步沒有什麼好介紹的,如果是有現有的組件項目,並且在Git的版本管理下,那麼這一步就算完成了,可以直接進行下一步了。
如果你的組件還在你冗余龐大的項目中,需要拆分出來或者需要自己從零開始創建一個組件庫,那麼我建議你使用Cocoapods提供的一個工具將第二步與第三步結合起來做。
現在來說一下這個工具,相關的文檔介紹是Using Pod Lib Create 就拿我創建的podTestLibrary為例子具體講一下這裡是如何操作的,先cd到要創建項目的目錄然後執行
$ pod lib create podTestLibrary
之後他會問你四個問題,1.是否需要一個例子工程;2.選擇一個測試框架;3.是否基於View測試;4.類的前綴;4個問題的具體介紹可以去看官方文檔,我這裡選擇的是1.yes;2.Specta/Expecta;3.yes;4.PTL。 問完這4個問題他會自動執行pod install命令創建項目並生成依賴。
$ tree PodTestLibrary -L 2 PodTestLibrary ├── Example #demo APP │ ├── PodTestLibrary │ ├── PodTestLibrary.xcodeproj │ ├── PodTestLibrary.xcworkspace │ ├── Podfile #demo APP 的依賴描述文件 │ ├── Podfile.lock │ ├── Pods #demo APP 的依賴文件 │ └── Tests ├── LICENSE #開源協議 默認MIT ├── Pod #組件的目錄 │ ├── Assets #資源文件 │ └── Classes #類文件 ├── PodTestLibrary.podspec #第三步要創建的podspec文件 └── README.md #markdown格式的README 9 directories, 5 files
以上是項目生成的目錄結構及相關介紹。
接下來就是向Pod文件夾中添加庫文件和資源,並配置podspec文件,我把一個網絡模塊的共有組件放入Pod/Classes中,然後進入Example文件夾執行pod update命令,再打開項目工程可以看到,剛剛添加的組件已經在Pods子工程下Development Pods/PodTestLibrary中了,然後編輯demo工程,測試組件,我並沒有使用提供的測試框架進行測試,這裡就先不介紹了。
注:這裡需要注意的是每當你向Pod中添加了新的文件或者以後更新了podspec的版本都需要重新執行一遍pod update命令。
測試無誤後需要將該項目添加並推送到遠端倉庫,並編輯podspec文件。
通過Cocoapods創建出來的目錄本身就在本地的Git管理下,我們需要做的就是給它添加遠端倉庫,同樣去GitHub或其他的Git服務提供商那裡創建一個私有的倉庫,拿到SSH地址,然後cd到PodTestLibrary目錄
$ git add . $ git commit -s -m "Initial Commit of Library" $ git remote add origin [email protected]:wtlucky/podTestLibrary.git #添加遠端倉庫 $ git push origin master #提交到遠端倉庫
因為podspec文件中獲取Git版本控制的項目還需要tag號,所以我們要打上一個tag,
$ git tag -m "first release" "0.1.0" $ git push --tags #推送tag到遠端倉庫
做完這些就可以開始編輯podspec文件了,它是一個Ruby的文件,把編輯器的格式改成Ruby就能看到語法高亮,下面我貼上我的podspec文件,並在後面以注釋的形式說明每個字段的含義,沒有涉及到的字段可以去官方文檔查閱
Pod::Spec.new do |s| s.name = "PodTestLibrary" #名稱 s.version = "0.1.0" #版本號 s.summary = "Just Testing." #簡短介紹,下面是詳細介紹 s.description = <<-DESC Testing Private Podspec. * Markdown format. * Don't worry about the indent, we strip it! DESC s.homepage = "https://coding.net/u/wtlucky/p/podTestLibrary" #主頁,這裡要填寫可以訪問到的地址,不然驗證不通過 # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" #截圖 s.license = 'MIT' #開源協議 s.author = { "wtlucky" => "[email protected]" } #作者信息 s.source = { :git => "https://coding.net/wtlucky/podTestLibrary.git", :tag => "0.1.0" } #項目地址,這裡不支持ssh的地址,驗證不通過,只支持HTTP和HTTPS,最好使用HTTPS # s.social_media_url = 'https://twitter.com/' #多媒體介紹地址 s.platform = :ios, '7.0' #支持的平台及版本 s.requires_arc = true #是否使用ARC,如果指定具體文件,則具體的問題使用ARC s.source_files = 'Pod/Classes/**/*' #代碼源文件地址,**/*表示Classes目錄及其子目錄下所有文件,如果有多個目錄下則用逗號分開,如果需要在項目中分組顯示,這裡也要做相應的設置 s.resource_bundles = { 'PodTestLibrary' => ['Pod/Assets/*.png'] } #資源文件地址 s.public_header_files = 'Pod/Classes/**/*.h' #公開頭文件地址 s.frameworks = 'UIKit' #所需的framework,多個用逗號隔開 s.dependency 'AFNetworking', '~> 2.3' #依賴關系,該項目所依賴的其他庫,如果有多個需要填寫多個s.dependency end
編輯完podspec文件後,需要驗證一下這個文件是否可用,如果有任何WARNING或者ERROR都是不可以的,它就不能被添加到Spec Repo中,不過xcode的WARNING是可以存在的,驗證需要執行一下命令
$ pod lib lint
當你看到
-> PodTestLibrary (0.1.0) PodTestLibrary passed validation.
時,說明驗證通過了,不過這只是這個podspec文件是合格的,不一定說明這個Pod是可以用的,我們需要在本地做一下驗證,這就是第四步的內容了,第四步在具體說明。
創建podspec文件
如果從第二步過來,已經有了現成的項目,那麼就需要給這個項目創建一個podspec文件,創建它需要執行Cocoapods的另外一個命令,官方文檔在這裡
$ pod spec create PodTestLibrary [email protected]:wtlucky/podTestLibrary.git
執行完之後,就創建了一個podspec文件,他其中會包含很多內容,可以按照我之前介紹的進行編輯,沒用的刪掉。編輯完成之後使用驗證命令驗證一下
$ pod lib lint
驗證無誤就可以進入下一步了。
本地測試podspec文件
我們可以創建一個新的項目,在這個項目的Podfile文件中直接指定剛才創建編輯好的podspec文件,看是否可用。 在Podfile中我們可以這樣編輯,有兩種方式
platform :ios, '7.0' pod 'PodTestLibrary', :path => '~/code/Cocoapods/podTest/PodTestLibrary' #指定路徑 pod 'PodTestLibrary', :podspec => '~/code/Cocoapods/podTest/PodTestLibrary/PodTestLibrary.podspec' #指定podspec文件
然後執行pod install命令安裝依賴,打開項目工程,可以看到庫文件都被加載到Pods子項目中了,不過它們並沒有在Pods目錄下,而是跟測試項目一樣存在於Development Pods/PodTestLibrary中,這是因為我們是在本地測試,而沒有把podspec文件添加到Spec Repo中的緣故。
在項目中編寫代碼,測試庫文件無誤後就可以開始下一步了,提交podspec到Spec Repo中。
向Spec Repo提交podspec
向Spec Repo提交podspec需要完成兩點一個是podspec必須通過驗證無誤,在一個就是刪掉無用的注釋(這個不是必須的,為了規范還是刪掉吧)。 向我們的私有Spec Repo提交podspec只需要一個命令
$ pod repo push WTSpecs PodTestLibrary.podspec #前面是本地Repo名字 後面是podspec名字
完成之後這個組件庫就添加到我們的私有Spec Repo中了,可以進入到~/.cocoapods/repos/WTSpecs目錄下查看
. ├── LICENSE ├── PodTestLibrary │ └── 0.1.0 │ └── PodTestLibrary.podspec └── README.md
再去看我們的Spec Repo遠端倉庫,也有了一次提交,這個podspec也已經被Push上去了。
至此,我們的這個組件庫就已經制作添加完成了,使用pod search命令就可以查到我們自己的庫了
$ pod search PodTestLibrary -> PodTestLibrary (0.1.0) Just Testing. pod 'PodTestLibrary', '~> 0.1.0' - Homepage: https://coding.net/u/wtlucky/p/podTestLibrary - Source: https://coding.net/wtlucky/podTestLibrary.git - Versions: 0.1.0 [WTSpecs repo]
這裡說的是添加到私有的Repo,如果要添加到Cocoapods的官方庫了,可以使用trunk工具,具體可以查看官方文檔。
使用制作好的Pod
在完成這一系列步驟之後,我們就可以在正式項目中使用這個私有的Pod了只需要在項目的Podfile裡增加以下一行代碼即可
$ pod 'PodTestLibrary', '~> 0.1.0'
然後執行pod update,更新庫依賴,然後打卡項目可以看到,我們自己的庫文件已經出現在Pods子項目中的Pods子目錄下了,而不再是Development Pods。
更新維護podspec
最後再來說一下制作好的podspec文件後續的更新維護工作,比如如何添加新的版本,如何刪除Pod。
我已經制作好了PodTestLibrary的0.1.0版本,現在我對他進行升級工作,這次我添加了更多的模塊到PodTestLibrary之中,包括工具類,底層Model及UIKit擴展等,這裡又嘗試了一下subspec功能,給PodTestLibrary創建了多個子分支。
具體做法是先將源文件添加到Pod/Classes中,然後按照不同的模塊對文件目錄進行整理,因為我有四個模塊,所以在Pod/Classes下有創建了四個子目錄,完成之後繼續編輯之前的PodTestLibrary.podspec,這次增加了subspec特性
Pod::Spec.new do |s| s.name = "PodTestLibrary" s.version = "1.0.0" s.summary = "Just Testing." s.description = <<-DESC Testing Private Podspec. * Markdown format. * Don't worry about the indent, we strip it! DESC s.homepage = "https://coding.net/u/wtlucky/p/podTestLibrary" # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" s.license = 'MIT' s.author = { "wtlucky" => "[email protected]" } s.source = { :git => "https://coding.net/wtlucky/podTestLibrary.git", :tag => "1.0.0" } # s.social_media_url = 'https://twitter.com/' s.platform = :ios, '7.0' s.requires_arc = true #s.source_files = 'Pod/Classes/**/*' #s.resource_bundles = { # 'PodTestLibrary' => ['Pod/Assets/*.png'] #} #s.public_header_files = 'Pod/Classes/**/*.h' s.subspec 'NetWorkEngine' do |networkEngine| networkEngine.source_files = 'Pod/Classes/NetworkEngine/**/*' networkEngine.public_header_files = 'Pod/Classes/NetworkEngine/**/*.h' networkEngine.dependency 'AFNetworking', '~> 2.3' end s.subspec 'DataModel' do |dataModel| dataModel.source_files = 'Pod/Classes/DataModel/**/*' dataModel.public_header_files = 'Pod/Classes/DataModel/**/*.h' end s.subspec 'CommonTools' do |commonTools| commonTools.source_files = 'Pod/Classes/CommonTools/**/*' commonTools.public_header_files = 'Pod/Classes/CommonTools/**/*.h' commonTools.dependency 'OpenUDID', '~> 1.0.0' end s.subspec 'UIKitAddition' do |ui| ui.source_files = 'Pod/Classes/UIKitAddition/**/*' ui.public_header_files = 'Pod/Classes/UIKitAddition/**/*.h' ui.resource = "Pod/Assets/MLSUIKitResource.bundle" ui.dependency 'PodTestLibrary/CommonTools' end s.frameworks = 'UIKit' #s.dependency 'AFNetworking', '~> 2.3' #s.dependency 'OpenUDID', '~> 1.0.0' end
因為我們創建了subspec所以項目整體的依賴dependency,源文件source_files,頭文件public_header_files,資源文件resource等都移動到了各自的subspec中,每個subspec之間也可以有相互的依賴關系,比如UIKitAddition就依賴於CommonTools。
編輯完成之後,在測試項目裡pod update一下,幾個子項目都被加進項目工程了,寫代碼驗證無誤之後,就可以將這個工程push到遠端倉庫,並打上新的tag->1.0.0。
最後再次使用pod lib lint驗證編輯好的podsepc文件,沒有自身的WARNING或者ERROR之後,就可以再次提交到Spec Repo中了,命令跟之前是一樣的
$ pod repo push WTSpecs PodTestLibrary.podspec
之後再次到~/.cocoapods/repos/WTSpecs目錄下查看
. ├── LICENSE ├── PodTestLibrary │ ├── 0.1.0 │ │ └── PodTestLibrary.podspec │ └── 1.0.0 │ └── PodTestLibrary.podspec └── README.md 3 directories, 4 files
已經有兩個版本了,使用pod search查找得到的結果為
$ pod search PodTestLibrary -> PodTestLibrary (1.0.0) Just Testing. pod 'PodTestLibrary', '~> 1.0.0' - Homepage: https://coding.net/u/wtlucky/p/podTestLibrary - Source: https://coding.net/wtlucky/podTestLibrary.git - Versions: 1.0.0, 0.1.0 [WTSpecs repo] - Sub specs: - PodTestLibrary/NetWorkEngine (1.0.0) - PodTestLibrary/DataModel (1.0.0) - PodTestLibrary/CommonTools (1.0.0) - PodTestLibrary/UIKitAddition (1.0.0)
完成這些之後,在實際項目中我們就可以選擇使用整個組件庫或者是組件庫的某一個部分了,對應的Podfile中添加的內容為
platform :ios, '7.0' pod 'PodTestLibrary/NetWorkEngine', '1.0.0' #使用某一個部分 pod 'PodTestLibrary/UIKitAddition', '1.0.0' pod 'PodTestLibrary', '1.0.0' #使用整個庫
最後介紹一下如何刪除一個私有Spec Repo,只需要執行一條命令即可
$ pod repo remove WTSpecs
這樣這個Spec Repo就在本地刪除了,我們還可以通過
$ pod repo add WTSpecs [email protected]:wtlucky/WTSpecs.git
再把它給加回來。
如果我們要刪除私有Spec Repo下的某一個podspec怎麼操作呢,此時無需借助Cocoapods,只需要cd到~/.cocoapods/repos/WTSpecs目錄下,刪掉庫目錄
wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ rm -Rf PodTestLibrary
然後在將Git的變動push到遠端倉庫即可
wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ git add --all . wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ git ci -m "remove unuseful pods" wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ git push origin master
參考資料
Private Pods
Creating a Private CocoaPod
Developing Private In-House Libraries with CocoaPods
(本文作者:wtlucky)