
CocoaPods是OS X和iOS下的一個(gè)第三方開(kāi)源類庫(kù)管理工具,通過(guò)CocoaPods工具我們可以為項(xiàng)目添加依賴庫(kù)(這些類庫(kù)必須是CocoaPods本身所支持的),并且可以輕松管理其版本。它是目前iOS開(kāi)發(fā)中使用最廣泛的開(kāi)源庫(kù)管理工具,如果我們內(nèi)部協(xié)作的組件化能夠使用這種方式管理的話,那將是很便利的。
在通過(guò)Cocoapods建立內(nèi)部私有庫(kù)之前,我們需要再熟悉下Cocoapods的工作流程,我們創(chuàng)建內(nèi)部私有庫(kù)時(shí)也會(huì)依照這個(gè)流程來(lái)。
本文目錄
一、Cocoapods的工作流程
二、建立Cocoapods私有庫(kù)
三、使用私有庫(kù)
四、問(wèn)題總結(jié)
Cocoapods工作流程
工作流程如圖所示:

遠(yuǎn)程索引庫(kù):
這里存放了各個(gè)框架的描述文件,托管在github上:
CocoaPods/Specs
本地索引庫(kù):
在安裝cocoapods時(shí),執(zhí)行的pod setup就是講遠(yuǎn)程索引克隆到本地,本地索引的目錄為:
~/.cocoapods/repos/master
本地索引和遠(yuǎn)程索引的目錄一致,結(jié)構(gòu)如下:

每個(gè)庫(kù)的每個(gè)版本都對(duì)應(yīng)一個(gè)json格式的描述文件:
{
"name": "YYImage",
"summary": "Image framework for iOS to display/encode/decode animated WebP, APNG, GIF, and more.",
"version": "1.0",
"license": {
"type": "MIT",
"file": "LICENSE"
},
"authors": {
"ibireme": "ibireme@gmail.com"
},
"social_media_url": "http://blog.ibireme.com",
"homepage": "https://github.com/ibireme/YYImage",
"platforms": {
"ios": "6.0"
},
"source": {
"git": "https://github.com/ibireme/YYImage.git",
"tag": "1.0"
},
"requires_arc": true,
"default_subspecs": "Core",
"subspecs": [
{
"name": "Core",
"source_files": "YYImage/*.{h,m}",
"public_header_files": "YYImage/*.{h}",
"libraries": "z",
"frameworks": [
"UIKit",
"CoreFoundation",
"QuartzCore",
"AssetsLibrary",
"ImageIO",
"Accelerate",
"MobileCoreServices"
]
},
{
"name": "WebP",
"dependencies": {
"YYImage/Core": [
]
},
"ios": {
"vendored_frameworks": "Vendor/WebP.framework"
}
}
]
}
本地索引文件
當(dāng)執(zhí)行pod search命令時(shí),如果本地索引不存在,就會(huì)創(chuàng)建出來(lái):
$ pod search afn
Creating search index for spec repo 'master'..
本地索引文件路徑為:
~/Library/Cache/Cocoapods/Pods
遠(yuǎn)程框架庫(kù)
以YYImage為例,它的遠(yuǎn)程框架庫(kù)就是json文件中的source:
https://github.com/ibireme/YYImage.git
所以再用文字總結(jié)下Cocoapods工作流程大概就是
1、本地安裝cocoapods,建立本地索引庫(kù)和遠(yuǎn)程索引庫(kù)的映射
2、本地項(xiàng)目pod install
3、查找本地索引文件,然后找到各個(gè)庫(kù)對(duì)應(yīng)版本的json文件
4、通過(guò)json文件source字段找到引用庫(kù)的git地址
5、把庫(kù)文件拉到本地項(xiàng)目
建立Cocoapods私有庫(kù)(framework)
建議采用framework的形式創(chuàng)建私有庫(kù),這可以很好的在開(kāi)發(fā)階段檢查出庫(kù)的不兼容或者文件權(quán)限出現(xiàn)的問(wèn)題,Swift編寫的代碼通過(guò)Cocoapods生成的都是framework。
0、準(zhǔn)備工作:
如何建立遠(yuǎn)程索引庫(kù)
首先我們需要建立一個(gè)內(nèi)部的遠(yuǎn)程索引庫(kù),類似Cocoapods/Spec的功能,之后添加的庫(kù)文件索引文件都會(huì)存放到這里:https://zhangferry@bitbucket.org/sealcn/sealrepo.git
建立本地和遠(yuǎn)程索引倉(cāng)庫(kù)的關(guān)聯(lián):
pod repo add SealRepo https://zhangferry@bitbucket.org/sealcn/sealrepo.git
執(zhí)行pod repo

可以看到我們有了兩個(gè)索引倉(cāng)庫(kù),可以去在這個(gè)目錄~/.cocoapods/repos看到我們剛建立的SealRepo。
如何組織文件結(jié)構(gòu)
我們可以看下Alamofire的文件組織結(jié)構(gòu):

我們看到這幾個(gè)文件:
-
Source用于存放Framework源文件, -
Example用于放Demo項(xiàng)目 -
docs和Documentation放說(shuō)明文檔,這個(gè)是可選的, -
Tests測(cè)試文件也是可選。
我們制作私有庫(kù)時(shí)會(huì)仿照這個(gè)格式。
一、制作framework

因?yàn)槭荢wift的工程,接口的開(kāi)放直接通過(guò)open、public等關(guān)鍵字指定,所以工程中的ABTest.h頭文件可以刪除,加入我們自己的庫(kù)文件。

注意:在寫公有庫(kù)文件時(shí),對(duì)外界開(kāi)放的屬性,方法需要帶上
public或者open關(guān)鍵字。
二、添加Example工程
通過(guò)Xcode菜單欄File->New->Target...添加一個(gè)Example工程。
引入第三方庫(kù)
如果無(wú)第三庫(kù)引用可以跳過(guò)這一步。
注意:引入Podfile文件,需要framework和Example兩個(gè)target都添加上。
測(cè)試項(xiàng)目
需要先編譯framework,沒(méi)有問(wèn)題之后,導(dǎo)入到Demo項(xiàng)目里
import ABTest
運(yùn)行Dome,測(cè)試開(kāi)發(fā)功能有沒(méi)有問(wèn)題。
push項(xiàng)目到遠(yuǎn)程庫(kù)
如果已經(jīng)關(guān)聯(lián)過(guò)遠(yuǎn)程私有倉(cāng)庫(kù),這一步可以跳過(guò)。
在遠(yuǎn)程配置一個(gè)git地址,然后將本地項(xiàng)目關(guān)聯(lián)到遠(yuǎn)程私有倉(cāng)庫(kù):
git remote add origin 倉(cāng)庫(kù)地址
如過(guò)是首次關(guān)聯(lián)遠(yuǎn)程倉(cāng)庫(kù),在push之前我們一般需要先拉去遠(yuǎn)程分支
git pull origin master
如果提示:
There is no tracking information for the current branch.
那是因?yàn)楸镜貛?kù)和遠(yuǎn)程庫(kù)沒(méi)有建立聯(lián)系,git認(rèn)為這兩個(gè)倉(cāng)庫(kù)可能不是同一個(gè),如果我們確認(rèn)對(duì)應(yīng)庫(kù)沒(méi)問(wèn)題,可以使用:
$ git pull origin master --allow-unrelated-histories
將遠(yuǎn)程庫(kù)文件強(qiáng)制拉到本地倉(cāng)庫(kù)。
之后再執(zhí)行push命令將項(xiàng)目推到遠(yuǎn)程倉(cāng)庫(kù)。
git push -u origin master
三、Cocoapods配置文件
1、添加.swift-version
.swift-version文件用來(lái)告訴cocoapods當(dāng)前文件swift的版本,用命令行建立:
$ echo "3.0" > .swift-version
2、添加LICENSE
每個(gè)使用cocoapods添加的庫(kù)都需要準(zhǔn)守開(kāi)源協(xié)議,一般是MIT協(xié)議,因?yàn)閎itbucket沒(méi)法自動(dòng)生成,我們可以手動(dòng)生成這個(gè)同名文件,然后把協(xié)議內(nèi)容復(fù)制進(jìn)去:
MIT License
Copyright (c) [year] [fullname]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
3、創(chuàng)建庫(kù)描述文件
可以通過(guò)命令行生成描述文件:
$ pod spec create ABTest
然后我們編輯ABTest.podspec文件,可以仿照下面的寫法
Pod::Spec.new do |s|
s.name = "ABTest"
s.version = "0.0.1"
s.summary = "ABTest with Firebase"
s.description = "This is a ABTest Framworks on swift"
s.homepage = "https://bitbucket.org/sealcn/remoteabtest/src/master/"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "zhangferry" => "zhangfei@dailyinnovation.biz" }
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.platform = :ios, "8.0"
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.source = { :git => "https://zhangferry@bitbucket.org/sealcn/remoteabtest.git", :tag => s.version }
s.source_files = "Source", "Source/*.swift"
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# s.resource = "icon.png"
# s.resources = "Resources/*.png"
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.requires_arc = true
s.static_framework = true
s.dependency "Firebase/Core"
s.dependency "Firebase/RemoteConfig"
#s.ios.vendored_frameworks = "ABTest.framework"
s.xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/Firebase/CoreOnly/Sources' }
end
此時(shí)我們的文件目錄看起來(lái)應(yīng)該大概是這個(gè)樣子:

4、驗(yàn)證本地podspec文件
pod lib lint
該命令用于檢查podspec文件書寫是否正確,如果有error需要解決,warning可以不用管(可能會(huì)遇到較多問(wèn)題,需耐心解決0。0)。解決之后再次運(yùn)行檢查命令,當(dāng)命令行顯示:
-> ABTest (0.0.1)
ABTest passed validation.
說(shuō)明我們本地配置成功了,到這里本地的第一個(gè)版本就算完成了!
然后我們需要將本次修改提交打上tag,提交到遠(yuǎn)程倉(cāng)庫(kù)。
git add .
git commit -m "build v0.0.1"
git tag 0.0.1
git push --tags
5、驗(yàn)證遠(yuǎn)程索引文件
上傳代碼成功之后,我們需要再次驗(yàn)證它跟遠(yuǎn)程倉(cāng)庫(kù)(ABTest遠(yuǎn)程庫(kù)和.podspec)是否匹配正確,執(zhí)行:
pod spec lint
當(dāng)出現(xiàn):
ABTest.podspec passed validation
時(shí),說(shuō)明我們遠(yuǎn)程倉(cāng)庫(kù)匹配正確。
6、提交podspec文件到SpecsRepo
$ pod repo push SealRepo ABTest.podspec
這個(gè)命令會(huì)包含pod spec lint命令,驗(yàn)證通過(guò)之后,會(huì)添加.podspec文件到本地索引庫(kù):

和遠(yuǎn)程索引庫(kù):

使用私有庫(kù)
引用私有庫(kù)
我們可以像使用其他庫(kù)文件一樣在Podfile文件中添加使用私有庫(kù)了,引入方法有兩種:
1、全局添加
在Podfile文件最上面添加一行:
source 'https://zhangferry@bitbucket.org/sealcn/sealrepo.git'
注意:如果私有倉(cāng)庫(kù)和cocoapods倉(cāng)庫(kù)出現(xiàn)同名庫(kù),會(huì)出現(xiàn)不可預(yù)期的情況(隨機(jī)拉下來(lái)公有庫(kù)或者私有庫(kù)文件)。這時(shí)我們需要使用單獨(dú)添加的方式。
2、單獨(dú)添加
pod 'ABTest', :git => 'https://zhangferry@bitbucket.org/sealcn/remoteabtest.git'
使用時(shí)通過(guò)import方法導(dǎo)入庫(kù)就可以了。
更新私有庫(kù)
當(dāng)我們需要升級(jí)私有庫(kù),添加或者修改方法時(shí),只需要:
1、修改.podspec文件中s.version的版本號(hào)
2、提交本地修改至遠(yuǎn)程,打上對(duì)應(yīng)tag
3、使用項(xiàng)目的工程執(zhí)行pod update
可能遇到的問(wèn)題
1、pod search 查不到本地庫(kù)
這個(gè)可能是cocoadpods本身問(wèn)題,pod install安裝沒(méi)有問(wèn)題
2、更新了版本,但是pod update沒(méi)有找到
我們可以采用如下形式,手動(dòng)指定版本號(hào):
pod 'ABTest', :git => 'https://zhangferry@bitbucket.org/sealcn/remoteabtest.git', :tag => '0.0.4'
3、提示The 'Pods-App' target has transitive dependencies that include static binaries
這是因?yàn)橐氲膸?kù)被編譯成了靜態(tài)庫(kù),我們可以在.podspec文件中加入:
s.static_framework = true
4、引入的第三方庫(kù),在pod lint時(shí)提示找不到
可以手動(dòng)指定pod目錄,將firsebase替換成你的庫(kù)文件路徑:
s.xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/Firebase/CoreOnly/Sources' }
5、提示source_files對(duì)應(yīng)文件為空
每次pod lint時(shí)都是根據(jù)版本號(hào)進(jìn)行查找的,可以檢查下當(dāng)前修改跟版本號(hào)是否對(duì)應(yīng)。