整體流程
整體先說明一下創(chuàng)建一個私有的podspec包括如下那么幾個步驟:
- 創(chuàng)建并設(shè)置一個私有的Spec Repo衔峰。
- 創(chuàng)建Pod的所需要的項目工程文件,并且有可訪問的項目版本控制地址。
- 創(chuàng)建Pod所對應(yīng)的podspec文件垫卤。
- 本地測試配置好的podspec文件是否可用威彰。
- 向私有的Spec Repo中提交podspec。
- 在個人項目中的Podfile中增加剛剛制作的好的Pod并使用穴肘。
- 更新維護podspec歇盼。
1. 創(chuàng)建私有Spec Repo
Spec Repo是所有的Pods的一個索引,就是一個容器评抚,所有公開的Pods都在這個里面豹缀,它實際是一個Git倉庫remote端在GitHub上,但是當(dāng)你使用了Cocoapods后它會被clone到本地的~/.cocoapods/repos目錄下慨代,可以進入到這個目錄看到master文件夾就是這個官方的Spec Repo了邢笙。這個master目錄的結(jié)構(gòu)大概就是這個樣子的:
Specs - [SPEC_NAME] - [VERSION] - [SPEC_NAME].podspec
首先鱼响,創(chuàng)建一個 Git倉庫鸣剪,這個倉庫你可以創(chuàng)建私有的也可以創(chuàng)建公開的,不過既然私有的Spec Repo丈积,還是創(chuàng)建私有的倉庫吧筐骇,需要注意的就是如果項目中有其他同事共同開發(fā)的話,你還要給他這個Git倉庫的權(quán)限江滨。
創(chuàng)建完成之后終端中執(zhí)行以下命令:
pod repo add [私有Spec RepoName] [倉庫地址]
比如: pod repo add WTSpecs https://coding.net/wtlucky/WTSpecs.git
此時如果成功的話進入到 ~/.cocoapods/repos 目錄下就可以看到WTSpecs這個目錄了铛纬。至此第一步創(chuàng)建私有Spec Repo完成。
Note:如果有其他合作人員共同使用這個私有Spec Repo的話在他有對應(yīng)Git倉庫的權(quán)限的前提下執(zhí)行相同的命令添加這個Spec Repo即可唬滑。
2. 創(chuàng)建Pod項目工程文件
這個第二步?jīng)]有什么好介紹的告唆,如果是有現(xiàn)有的組件項目,并且在Git的版本管理下晶密,那么這一步就算完成了擒悬,可以直接跳過這個步驟了。
如果你的組件還在你冗余龐大的項目中稻艰,需要拆分出來或者需要自己從零開始創(chuàng)建一個組件庫懂牧,那么我建議你使用Cocoapods提供的一個工具將第二步與第三步結(jié)合起來做。
現(xiàn)在來說一下這個工具尊勿,相關(guān)的文檔介紹是Using Pod Lib Create 僧凤,就拿我創(chuàng)建的podTestLibrary為例子具體講一下這里是如何操作的,先cd到要創(chuàng)建項目的目錄然后執(zhí)行:
pod lib create podTestLibrary
然后元扔,等待一會兒躯保, 它會問您幾個問題?
- What platform do you want to use?? [ iOS / macOS ]
- What language do you want to use?? [ Swift / ObjC ]
- Would you like to include a demo application with your library? [ Yes / No ]
- Which testing frameworks will you use? [ Specta / Kiwi / None ]
- Would you like to do view based testing? [ Yes / No ]
- What is your class prefix?
翻譯下來澎语,按自己需求回答即可途事。
然后验懊,就可以看到在剛才的目錄下面,成功生成了以下文件
$ tree PodTestLibrary -L 2
PodTestLibrary
├── Example #demo APP
│ ├── PodTestLibrary
│ ├── PodTestLibrary.xcodeproj
│ ├── PodTestLibrary.xcworkspace
│ ├── Podfile #demo APP 的依賴描述文件
│ ├── Podfile.lock
│ ├── Pods #demo APP 的依賴文件
│ └── Tests
├── LICENSE #開源協(xié)議 默認(rèn)MIT
├── Pod #組件的目錄
│ ├── Assets #資源文件
│ └── Classes #類文件
├── PodTestLibrary.podspec #第三步要創(chuàng)建的podspec文件
└── README.md #markdown格式的README
以上是項目生成的目錄結(jié)構(gòu)及相關(guān)介紹尸变。
接下來就是向Pod文件夾中添加庫文件和資源鲁森,并配置podspec文件,我把一個網(wǎng)絡(luò)模塊的共有組件放入Pod/Classes中振惰,然后進入Example文件夾執(zhí)行pod update命令歌溉,再打開項目工程可以看到,剛剛添加的組件已經(jīng)在Pods子工程下Development Pods/PodTestLibrary中了骑晶,然后編輯demo工程痛垛,測試組件,我并沒有使用提供的測試框架進行測試桶蛔,這里就先不介紹了匙头。
Note:這里需要注意的是每當(dāng)你向Pod中添加了新的文件或者以后更新了podspec的版本都需要重新執(zhí)行一遍pod update命令。
測試無誤后需要將該項目添加并推送到遠端倉庫仔雷,并編輯podspec文件蹂析。
通過Cocoapods創(chuàng)建出來的目錄本身就在本地的Git管理下,我們需要做的就是給它添加遠端倉庫碟婆,同樣去GitHub或其他的Git服務(wù)提供商那里創(chuàng)建一個私有的倉庫电抚,拿到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文件,并在后面以注釋的形式說明每個字段的含義淌铐,沒有涉及到的字段可以去官方文檔查閱
| `01`|`Pod::Spec.``new` `do` `|s|` |
| `02` | `s.name = ``"PodTestLibrary"` `#名稱` |
| `03` | `s.version = ``"0.1.0"` `#版本號` |
| `04` | `s.summary = ``"Just Testing."` `#簡短介紹肺然,下面是詳細介紹` |
| `05` | `s.description = <<-DESC` |
| `06` | `Testing Private Podspec.` |
| `07` | |
| `08` | `* Markdown format.` |
| `09` | `* Don't worry about the indent, we strip it!` |
| `10` | `DESC` |
| `11` | `s.homepage = ``"[https://coding.net/u/wtlucky/p/podTestLibrary](https://coding.net/u/wtlucky/p/podTestLibrary)"` `#主頁,這里要填寫可以訪問到的地址,不然驗證不通過` |
| `12` | `# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" #截圖` |
| `13` | `s.license = ``'MIT'` `#開源協(xié)議` |
| `14` | `s.author = { ``"wtlucky"` `=> ``"wtlucky@foxmail.com"` `} ``#作者信息` |
| `15` | `s.source = { :git => ``"[https://coding.net/wtlucky/podTestLibrary.git](https://coding.net/wtlucky/podTestLibrary.git)"``, :tag => ``"0.1.0"` `} ``#項目地址腿准,這里不支持ssh的地址际起,驗證不通過,只支持HTTP和HTTPS释涛,最好使用HTTPS` |
| `16` | `# s.social_media_url = '[https://twitter.com/<twitter_username](https://twitter.com/%3Ctwitter_username)>' #多媒體介紹地址` |
| `17` | |
| `18` | `s.platform = :ios, ``'7.0'` `#支持的平臺及版本` |
| `19` | `s.requires_arc = ``true` `#是否使用ARC加叁,如果指定具體文件倦沧,則具體的問題使用ARC` |
| `20` | |
| `21` | `s.source_files = ``'Pod/Classes/**/*'` `#代碼源文件地址唇撬,**/*表示Classes目錄及其子目錄下所有文件,如果有多個目錄下則用逗號分開展融,如果需要在項目中分組顯示窖认,這里也要做相應(yīng)的設(shè)置` |
| `22` | `s.resource_bundles = {` |
| `23` | `'PodTestLibrary'` `=> [``'Pod/Assets/*.png'``]` |
| `24` | `} ``#資源文件地址` |
| `25` | |
| `26` | `s.public_header_files = ``'Pod/Classes/**/*.h'` `#公開頭文件地址` |
| `27` | `s.frameworks = ``'UIKit'` `#所需的framework,多個用逗號隔開` |
| `28` | `s.dependency ``'AFNetworking'``, ``'~> 2.3'` `#依賴關(guān)系,該項目所依賴的其他庫扑浸,如果有多個需要填寫多個s.dependency` |
| `29` | `end</twitter_username>` |
編輯完podspec文件后烧给,需要驗證一下這個文件是否可用,如果有任何WARNING或者ERROR都是不可以的喝噪,它就不能被添加到Spec Repo中础嫡,不過xcode的WARNING是可以存在的,驗證需要執(zhí)行一下命令
pod lib lint
當(dāng)你看到
1 -> PodTestLibrary (0.1.0)
2
3 PodTestLibrary passed validation.
時酝惧,說明驗證通過了榴鼎,不過這只是這個podspec文件是合格的,不一定說明這個Pod是可以用的晚唇,我們需要在本地做一下驗證巫财,這就是第四步的內(nèi)容了,第四步在具體說明哩陕。
3. 創(chuàng)建podspec文件
如果從第二步過來平项,已經(jīng)有了現(xiàn)成的項目,那么就需要給這個項目創(chuàng)建一個podspec文件悍及,創(chuàng)建它需要執(zhí)行Cocoapods的另外一個命令:
pod spec create PodTestLibrary git@coding.net:wtlucky/podTestLibrary.git
執(zhí)行完之后闽瓢,就創(chuàng)建了一個podspec文件,他其中會包含很多內(nèi)容心赶,可以按照我之前介紹的進行編輯鸳粉,沒用的刪掉。編輯完成之后使用驗證命令驗證一下
pod lib lint
驗證無誤就可以進入下一步了园担。
4. 本地測試podspec文件
我們可以創(chuàng)建一個新的項目届谈,在這個項目的Podfile文件中直接指定剛才創(chuàng)建編輯好的podspec文件,看是否可用弯汰。 在Podfile中我們可以這樣編輯艰山,有兩種方式
1 platform :ios, '7.0'
2
3 pod 'PodTestLibrary', :path => '~/code/Cocoapods/podTest/PodTestLibrary' #指定路徑
4 pod 'PodTestLibrary', :podspec => '~/code/Cocoapods/podTest/PodTestLibrary/PodTestLibrary.podspec' #指定podspec文件
然后執(zhí)行pod install命令安裝依賴,打開項目工程咏闪,可以看到庫文件都被加載到Pods子項目中了曙搬,不過它們并沒有在Pods目錄下,而是跟測試項目一樣存在于Development Pods/PodTestLibrary中鸽嫂,這是因為我們是在本地測試纵装,而沒有把podspec文件添加到Spec Repo中的緣故。
在項目中編寫代碼据某,測試庫文件無誤后就可以開始下一步了橡娄,提交podspec到Spec Repo中。
5. 向Spec Repo提交podspec
向Spec Repo提交podspec需要完成兩點一個是podspec必須通過驗證無誤癣籽,在一個就是刪掉無用的注釋(這個不是必須的挽唉,為了規(guī)范還是刪掉吧)滤祖。 向我們的私有Spec Repo提交podspec只需要一個命令:
pod repo push WTSpecs PodTestLibrary.podspec #前面是本地Repo名字 后面是podspec名字
如果有warning 但是沒有error,提示驗證不通過可以增加忽略警告的參數(shù):
pod repo push 本地repo名 NAME.podspec --verbose --use-libraries --allow-warnings
完成之后這個組件庫就添加到我們的私有Spec Repo中了,可以進入到~/.cocoapods/repos/WTSpecs目錄下查看:
1 .
2 ├── LICENSE
3 ├── PodTestLibrary
4 │ └── 0.1.0
5 │ └── PodTestLibrary.podspec
6 └── README.md
再去看我們的Spec Repo遠端倉庫瓶籽,也有了一次提交匠童,這個podspec也已經(jīng)被Push上去了。
至此塑顺,我們的這個組件庫就已經(jīng)制作添加完成了汤求,使用pod search命令就可以查到我們自己的庫了:
1 $ pod search PodTestLibrary
2
3 -> PodTestLibrary (0.1.0)
4 Just Testing.
5 pod 'PodTestLibrary', '~> 0.1.0'
6 - Homepage: https://coding.net/u/wtlucky/p/podTestLibrary
7 - Source: https://coding.net/wtlucky/podTestLibrary.git
8 - Versions: 0.1.0 [WTSpecs repo]
這里說的是添加到私有的Repo,如果要添加到Cocoapods的官方庫了严拒,可以使用trunk工具首昔,具體可以查看官方文檔。
6. 使用制作好的Pod
在完成這一系列步驟之后糙俗,我們就可以在正式項目中使用這個私有的Pod了需要在項目的Podfile里增加以下一行代碼:
pod 'PodTestLibrary', '~> 0.1.0'
并且在podfile文件上面加入兩個source地址:
source 'https://github.com/CocoaPods/Specs.git' // 官方的
source 'https://coding.net/wtlucky/podTestLibrary.git' // 自己的倉庫git地址
然后執(zhí)行pod update勒奇,更新庫依賴,然后打開項目可以看到巧骚,我們自己的庫文件已經(jīng)出現(xiàn)在Pods子項目中的Pods子目錄下了赊颠,而不再是Development Pods。
7. 更新維護podspec
最后再來說一下制作好的podspec文件后續(xù)的更新維護工作劈彪,比如如何添加新的版本竣蹦,如何刪除Pod。
我已經(jīng)制作好了PodTestLibrary的0.1.0版本沧奴,現(xiàn)在我對他進行升級工作痘括,這次我添加了更多的模塊到PodTestLibrary之中,包括工具類滔吠,底層Model及UIKit擴展等纲菌,這里又嘗試了一下subspec功能,給PodTestLibrary創(chuàng)建了多個子分支疮绷。
具體做法是先將源文件添加到Pod/Classes中翰舌,然后按照不同的模塊對文件目錄進行整理,因為我有四個模塊冬骚,所以在Pod/Classes下有創(chuàng)建了四個子目錄椅贱,完成之后繼續(xù)編輯之前的PodTestLibrary.podspec,這次增加了subspec特性
| `01` | `Pod::Spec.``new` `do` `|s|` |
| `02` | `s.name = ``"PodTestLibrary"` |
| `03` | `s.version = ``"1.0.0"` |
| `04` | `s.summary = ``"Just Testing."` |
| `05` | `s.description = <<-DESC` |
| `06` | `Testing Private Podspec.` |
| `07` | |
| `08` | `* Markdown format.` |
| `09` | `* Don't worry about the indent, we strip it!` |
| `10` | `DESC` |
| `11` | `s.homepage = ``"[https://coding.net/u/wtlucky/p/podTestLibrary](https://coding.net/u/wtlucky/p/podTestLibrary)"` |
| `12` | `# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"` |
| `13` | `s.license = ``'MIT'` |
| `14` | `s.author = { ``"wtlucky"` `=> ``"wtlucky@foxmail.com"` `}` |
| `15` | `s.source = { :git => ``"[https://coding.net/wtlucky/podTestLibrary.git](https://coding.net/wtlucky/podTestLibrary.git)"``, :tag => ``"1.0.0"` `}` |
| `16` | `# s.social_media_url = '[https://twitter.com/<twitter_username](https://twitter.com/%3Ctwitter_username)>'` |
| `17` | |
| `18` | `s.platform = :ios, ``'7.0'` |
| `19` | `s.requires_arc = ``true` |
| `20` | |
| `21` | `#s.source_files = 'Pod/Classes/**/*'` |
| `22` | `#s.resource_bundles = {` |
| `23` | `# 'PodTestLibrary' => ['Pod/Assets/*.png']` |
| `24` | `#}` |
| `25` | `#s.public_header_files = 'Pod/Classes/**/*.h'` |
| `26` | |
| `27` | `s.subspec ``'NetWorkEngine'` `do` `|networkEngine|` |
| `28` | `networkEngine.source_files = ``'Pod/Classes/NetworkEngine/**/*'` |
| `29` | `networkEngine.public_header_files = ``'Pod/Classes/NetworkEngine/**/*.h'` |
| `30` | `networkEngine.dependency ``'AFNetworking'``, ``'~> 2.3'` |
| `31` | `end` |
| `32` | |
| `33` | `s.subspec ``'DataModel'` `do` `|dataModel|` |
| `34` | `dataModel.source_files = ``'Pod/Classes/DataModel/**/*'` |
| `35` | `dataModel.public_header_files = ``'Pod/Classes/DataModel/**/*.h'` |
| `36` | `end` |
| `37` |
| `38` | s.subspec 'CommonTools' do |commonTools|
| `39` | commonTools.source_files = 'Pod/Classes/CommonTools/**/*'
| `40` | commonTools.public_header_files = 'Pod/Classes/CommonTools/**/*.h'
| `41` | commonTools.dependency 'OpenUDID', '~> 1.0.0'
| `42` | end
| `43` |
| `44` | s.subspec 'UIKitAddition' do |ui|
| `45` | ui.source_files = 'Pod/Classes/UIKitAddition/**/*'
| `46` | ui.public_header_files = 'Pod/Classes/UIKitAddition/**/*.h'
| `47` | ui.resource = "Pod/Assets/MLSUIKitResource.bundle"
| `48` | ui.dependency 'PodTestLibrary/CommonTools'
| `49` | end
| `50` |
| `51` | s.frameworks = 'UIKit'
| `52` | #s.dependency 'AFNetworking', '~> 2.3'
| `53` | #s.dependency 'OpenUDID', '~> 1.0.0'
| `54` | end</twitter_username>
因為我們創(chuàng)建了subspec所以項目整體的依賴dependency只冻,源文件source_files庇麦,頭文件public_header_files,資源文件resource等都移動到了各自的subspec中喜德,每個subspec之間也可以有相互的依賴關(guān)系山橄,比如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目錄下查看
01 .
02 ├── LICENSE
03 ├── PodTestLibrary
04 │ ├── 0.1.0
05 │ │ └── PodTestLibrary.podspec
06 │ └── 1.0.0
07 │ └── PodTestLibrary.podspec
08 └── README.md
09
10 3 directories, 4 files
已經(jīng)有兩個版本了馁蒂,使用pod search查找得到的結(jié)果為
01 $ pod search PodTestLibrary
02
03 -> PodTestLibrary (1.0.0)
04 Just Testing.
05 pod 'PodTestLibrary', '~> 1.0.0'
06 - Homepage: https://coding.net/u/wtlucky/p/podTestLibrary
07 - Source: https://coding.net/wtlucky/podTestLibrary.git
08 - Versions: 1.0.0, 0.1.0 [WTSpecs repo]
09 - Sub specs:
10 - PodTestLibrary/NetWorkEngine (1.0.0)
11 - PodTestLibrary/DataModel (1.0.0)
12 - PodTestLibrary/CommonTools (1.0.0)
13 - PodTestLibrary/UIKitAddition (1.0.0)
完成這些之后呵晚,在實際項目中我們就可以選擇使用整個組件庫或者是組件庫的某一個部分了,對應(yīng)的Podfile中添加的內(nèi)容為
1 platform :ios, '7.0'
2
3 pod 'PodTestLibrary/NetWorkEngine', '1.0.0' #使用某一個部分
4 pod 'PodTestLibrary/UIKitAddition', '1.0.0'
5
6 pod 'PodTestLibrary', '1.0.0' #使用整個庫
最后介紹一下如何刪除一個私有Spec Repo沫屡,只需要執(zhí)行一條命令即可
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到遠端倉庫即可
1 wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ git add --all .
2 wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ git ci -m "remove unuseful pods"
3 wtlucky@wtluckydeMacBook-Pro:~/.cocoapods/repos/WTSpecs$ git push origin master