【原+轉】建立CocoaPods私有podspec

在個人上一篇文章《iOS 手把手教你發佈代碼到CocoaPods》中着重介紹如何將本身的代碼索引添加到公開的CocoaPods中,當你須要主動地向大衆開源你的代碼時須要那麼作。但在現實中咱們每每會有這種需求:既想享受CocoaPods所帶來的遍歷,又不想讓別人知道這些代碼,好比企業項目託管就會有這個需求。這篇文章就是解決建立私有podspec的問題。html

注:文章的大部份內容轉自這裏,關鍵部分我會加入本身在實踐過程當中的體會。ios

Cocoapods是很是好用的一個iOS依賴管理工具,使用它能夠方便的管理和更新項目中所使用到的第三方庫,以及將本身的項目中的公共組件交由它去管理。Cocoapods的介紹及優勢本文就不在贅述,我開始使用Cocoapods仍是在兩年前,那個時候它剛剛出現,網上的資料還很是的少,就連他們本身的HomePage都十分的簡單,我就着手嘗試着使用了一下,用它管理起第三方庫確實是十分的方便順手。後來它有了更強大的功能就是本身建立podspec,更能夠設置私有的庫。git

春節回來上班,沒有什麼任務作,正好項目中有一些公共組件須要從龐大的項目體系中剝離出來,並且年前項目終於從SVN遷移到了Git,真是喜大普奔,大快人心!這樣項目使用Cocoapods就有了條件,正好趁着這兩天沒有什麼事情作,學習一下建立私有的podspec並在項目中部署使用,以及pods的subspec的建立及使用。xcode

總體先說明一下建立一個私有的podspec包括以下那麼幾個步驟:markdown

  1. 建立並設置一個私有的Spec Repo(repo地址1)。網絡

  2. 建立Pod的所須要的項目工程文件,而且有可訪問的項目版本控制地址(Repo地址2)。框架

  3. 建立Pod所對應的podspec文件。ssh

  4. 本地測試配置好的podspec文件是否可用。編輯器

  5. 向私有的Spec Repo中提交podspec。ide

  6. 在我的項目中的Podfile中增長剛剛製做的好的Pod並使用。

  7. 更新維護podspec。

在這一系列的步驟中須要建立兩個Git倉庫,分別是第一步和第二步(第二步不必定非要是Git倉庫,只要是能夠獲取到相關代碼文件就能夠,也能夠是SVN的,也能夠說zip包,區別就是在podspec中的source項填寫的內容不一樣),而且第一步只是在初次建立私有podspec時才須要,以後在建立其餘的只須要從第二步開始就能夠。本文只介紹在Git環境下的操做,其餘環境其餘方式暫不說明。


 注意:上述步驟中兩個Repo地址是不同的,地址1的做用相似於CocoaPods官方的spec repo,專門用來存放spec。地址2能夠是git、svn等連接,僅僅用來存放源代碼


 

1、建立私有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便可。

 

2、建立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 git@coding.net: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" => "wtlucky@foxmail.com" }                   #做者信息
  s.source           = { :git => "https://coding.net/wtlucky/podTestLibrary.git", :tag => "0.1.0" }      #項目地址,這裏不支持ssh的地址,驗證不經過,只支持HTTP和HTTPS,最好使用HTTPS。
# 這裏的s.source須指向存放源代碼的連接地址,而不是託管spec文件的repo地址 # s.social_media_url = 'https://twitter.com/<twitter_username>' #多媒體介紹地址 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</twitter_username>

 編輯完podspec文件後,須要驗證一下這個文件是否可用,若是有任何WARNING或者ERROR都是不能夠的,它就不能被添加到Spec Repo中,不過xcode的WARNING是能夠存在的,驗證須要執行一下命令

$ pod lib lint

當你看到

 -> PodTestLibrary (0.1.0)
 
PodTestLibrary passed validation.

時,說明驗證經過了,不過這只是這個podspec文件是合格的,不必定說明這個Pod是能夠用的,咱們須要在本地作一下驗證,這就是第四步的內容了,第四步在具體說明。

3、建立podspec文件

若是從第二步過來,已經有了現成的項目,那麼就須要給這個項目建立一個podspec文件,建立它須要執行Cocoapods的另一個命令,官方文檔在這裏

$ pod spec create PodTestLibrary git@coding.net:wtlucky/podTestLibrary.git

執行完以後,就建立了一個podspec文件,他其中會包含不少內容,能夠按照我以前介紹的進行編輯,沒用的刪掉。編輯完成以後使用驗證命令驗證一下

$ pod lib lint

驗證無誤就能夠進入下一步了。

4、本地測試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中。

5、向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工具,具體能夠查看官方文檔。  

6、使用製做好的Pod

在完成這一系列步驟以後,咱們就能夠在正式項目中使用這個私有的Pod了只須要在項目的Podfile裏增長如下一行代碼便可

$ pod 'PodTestLibrary', '~> 0.1.0'

而後執行pod update,更新庫依賴,而後打卡項目能夠看到,咱們本身的庫文件已經出如今Pods子項目中的Pods子目錄下了,而再也不是Development Pods。

7、更新維護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" => "wtlucky@foxmail.com" }
  s.source           = { :git => "https://coding.net/wtlucky/podTestLibrary.git", :tag => "1.0.0" }
  # s.social_media_url = 'https://twitter.com/<twitter_username>'
 
  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</twitter_username>

由於咱們建立了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 git@coding.net: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

相關文章
相關標籤/搜索