玩轉CocoaPods
作者:阿里-移動雲-大前端
CocoaPods作為iOS的依賴管理工具,已然成為iOS開發的標準工具(官方給出的資料,超過42W個庫和300W個App使用了CocoaPods)。
本篇文章,非講述CocoaPods的教學文章,而是圍繞使用CocoaPods的兩個主題:依賴管理
和Pod庫釋出
,講述些易忽略、混淆的關鍵點和不為熟知的用法。
執行pod env
,可檢視本地環境:
CocoaPods : 1.2.0
Ruby : ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
RubyGems : 2.5.1
Host : Mac OS X 10.13.2 (17C88)
Xcode : 9.2 (9C40b)
Git : git version 2.14.3 (Apple Git-98)
1. 依賴管理
1.1 Podfile
Podfile
是一個說明檔案,描述一個或多個Xcode工程Target的依賴庫,類似於Maven管理依賴的pom.xml檔案。
Podfile可以很簡單,也可以很複雜。
依賴版本號
- 依賴最新版本,不指定版本號:
pod `TestSDK`
- 依賴指定版本,明確寫明版本號:
pod `TestSDK`, `1.0`
- 使用邏輯運算子:
`> 1.0`,版本號大於1.0。
`>= 1.0`,版本號大於等於1.0。
`< 1.0`,版本號小於1.0。
`<= 1.0`,版本號小於等於1.0。
- 使用optimistic operator (
~>
):
`~> 1.0.1`,版本號範圍:1.0.1 <= version < 1.1
`~> 1.0`,版本號範圍:1.0 <= version < 2.0
`~> 0`,版本號範圍:0 <= version,無意義
實際使用時,可根據專案需求,靈活配置依賴版本號。
Hook
Podfile中可配置鉤子函式,在依賴庫安裝過程中會被呼叫。主要有兩個Hook函式:pre_install
和post_install
,接收的引數為:Pod::Installer,分別對應Pods工程安裝前和安裝後。
- pre_install配置示例如下:
pre_install do |installer|
puts `[Test] - pre_install here`
end
- post_install配置示例如下,Pods工程安裝後,讀取列印
iOS deploy target
預設配置,並將其修改為8.0。
post_install do |installer|
puts `[Test] - post_install here`
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
puts "[Test] - config:" + config.name + ", deploy target: " + config.build_settings[`IPHONEOS_DEPLOYMENT_TARGET`]
config.build_settings[`IPHONEOS_DEPLOYMENT_TARGET`] = `8.0`
end
end
end
1.2 pod install vs. pod update
-
Podfile.lock
- 該檔案用來記錄和追蹤生成的Pod版本。
-
pod install
- 每次執行
pod install
,都會重新下載並安裝pods。 -
pods的版本號從
Podfile.lock
檔案中獲取:- 有記錄的pods,直接下載安裝該記錄版本號的pods,不檢查對應pods是否有更新;(已經安裝的pods不會更新其版本)
- 無記錄的pods,查詢下載並安裝滿足
Podfile
中指定版本號條件的pods。
- 每次執行
-
pod update
- 完整命令為:
pod update [PODNAME]
,執行命令後,CocoaPods會無視Podfile.lock
鎖定的版本號,查詢並更新到,滿足Podfile
中指定版本號條件的最新版本pods;若沒有指定PODNAME
,預設更新Podfile中全部pods。
- 完整命令為:
-
pod outdated
- 滿足
Podfile
中指定版本號條件下,列出比Podfile.lock
中記錄鎖定的版本號新的pods。 - 實際執行
pod update
命令時,更新的pods即為執行pod outdated
列出的pods。
- 滿足
-
建議用法
- 工程首次執行
pod install
或pod update
,執行效果一致。 - 需要安裝新新增pod,建議執行
pod install
或pod update [NEW_POD]
,已安裝的其他pods版本不變,否則可能由於版本更新的不確定性引起適配問題。 - 明確更新某pod版本時,執行
pod update [PODNAME]
,明確更新全部pods版本時,執行pod update
。
- 工程首次執行
1.3 pod cache
-
pod cache list [NAME]
- 可列出本地pods快取記錄,執行
pod install
或pod update
時,若命中快取記錄,則直接從本地拉取。
- 可列出本地pods快取記錄,執行
-
pod cache clean [NAME]
- 刪除本地pods快取記錄。
- 執行
pod cache clean --all
,刪除全部快取記錄。 - 例:從私有CocoaPods倉庫拉取TestSDK v1.0.1,該記錄新增到本地快取;由於某些原因TestSDK使用同樣的版本號v1.0.1做了覆蓋釋出,可以先執行
pod cache clean TestSDK
,然後再執行pod update
,保證拉取到最新版本的v1.0.1 SDK檔案。
2. Pod庫釋出
CocoaPods除了做依賴管理外,也會將自實現的pod庫上傳到公共倉庫/私有倉庫。
2.1 podspec
podspec檔案,即Pod Specification
(Pod描述檔案),描述指定版本的pod庫資訊,包括:pod庫原始碼地址、檔案列表、配置資訊、描述資訊等。
執行pod spec create
,可建立生成.podspec
檔案,其為Ruby語法格式,修改後如下,例:
Pod::Spec.new do |spec|
spec.name = `Reachability`
spec.version = `3.1.0`
spec.license = { :type => `BSD` }
spec.homepage = `https://github.com/tonymillion/Reachability`
spec.authors = { `Tony Million` => `tonymillion@gmail.com` }
spec.summary = `ARC and GCD Compatible Reachability Class for iOS and OS X.`
spec.source = { :git => `https://github.com/tonymillion/Reachability.git`, :tag => `v3.1.0` }
spec.source_files = `Reachability.{h,m}`
spec.framework = `SystemConfiguration`
end
- 執行
pod ipc spec xx.podspec
,可將.podspec
檔案內容從Ruby轉換為json
格式:
{
"name": "Reachability",
"version": "3.1.0",
"license": {
"type": "BSD"
},
"homepage": "https://github.com/tonymillion/Reachability",
"authors": {
"Tony Million": "tonymillion@gmail.com"
},
"summary": "ARC and GCD Compatible Reachability Class for iOS and OS X.",
"source": {
"git": "https://github.com/tonymillion/Reachability.git",
"tag": "v3.1.0"
},
"source_files": "Reachability.{h,m}",
"frameworks": "SystemConfiguration"
}
2.2 私有倉庫Push
CocoaPods倉庫本質上是Git倉庫,倉庫裡儲存的是各pod庫所有版本的.podspec
或.podspec.json
描述檔案。
pod庫上傳,即對應Git倉庫的commit提交。
Pod庫上傳到公共倉庫,即向 公共Git倉庫 提交commit。
因此,CocoaPods私有倉庫的搭建,只需再準備一個Github/Gitlab倉庫;具體搭建流程不再描述,可參考官網教程:CocoaPods – Private Pods。
- 執行
pod repo push REPO [NAME.podspec]
上傳Pod庫到私有倉庫,REPO
為私有倉庫在本地的倉庫名。
準備上傳的Pod庫,如果對其他pod庫有依賴,需要在.podspec
檔案中宣告dependency
;同時執行pod repo push
命令時,新增--source
引數,宣告依賴要查詢的倉庫地址;支援配置多個倉庫地址,以,
分隔。
例:
# 準備上傳TestSDK到私有倉庫PrivateSpec,倉庫Git座標:git@github.com/xx/xx-specs.git
# TestSDK依賴ASDK和BSDK,其中ASDK位於公共master倉庫,BSDK位於私有倉庫
# 上傳TestSDK時執行命令如下:
pod repo push PrivateSpec TestSDK.podspec --verbose --allow-warnings --source=git@github.com/xx/xx-specs.git,git@github.com:CocoaPods/Specs.git
2.3 依賴衝突
如果只從CocoaPods master倉庫拉取Pods,則不會有依賴衝突問題。依賴問題是由於引入三方私有CocoaPods倉庫導致的。
首先來看pods依賴傳遞問題。
- Pods依賴傳遞
假設TestSDK依賴ASDK和BSDK,工程引入TestSDK後,執行pod install
或 pod update
,會將TestSDK、ASDK和BSDK一併拉取下來,這種可認為是依賴傳遞
。
- Pods依賴傳遞版本號管理
假設有依賴關係如下,TestSDK使用時,ASDK必須整合1.0.1版本,CSDK和ASDK(1.0.2)不能相容。
-
TestSDK(1.0.2)
- ASDK(1.0.2)
- BSDK(1.0.2)
-
CSDK(1.0.1)
- ASDK(1.0.1)
按下面的依賴配置,拉取下來的SDK版本如下,存在CSDK和ASDK不相容問題。
- TestSDK(1.0.2)
- ASDK(1.0.2)
- BSDK(1.0.2)
- CSDK(1.0.1)
pod `TestSDK`, `1.0.2`
pod `CSDK`, `1.0.1`
此時,需要顯式指定ASDK版本號,拉取下來SDK版本如下:
- TestSDK(1.0.2)
- ASDK(1.0.1)
- BSDK(1.0.2)
- CSDK(1.0.1)
pod `TestSDK`, `1.0.2`
pod `CSDK`, `1.0.1`
pod `ASDK`, `1.0.1`
- 依賴衝突問題
存在於同時整合master公共倉庫和私有倉庫時,或整合多個私有倉庫時。
假設有兩個私有倉庫PrivateSpec1和PrivateSpec2,有SDK依賴關係如下,其中ASDK1和ASDK2是同一SDK的不同Pod封裝。
PrivateSpec1:
-
TestSDK1(1.0.0)
- ASDK1(1.0.0)
PrivateSpec2:
-
TestSDK2(1.0.1)
- ASDK2(1.0.1)
若同時依賴PrivateSpec1中的TestSDK1和PrivateSpec2中的TestSDK2,則ASDK1(1.0.0)和ASDK2(1.0.1)會衝突。
若Pods依賴支援類似Maven依賴的exclude
,將ASDK1或ASDK2其中之一exclude
,可解決該問題,但CocoaPods並不支援類似操作。
- 方法1,可手動整合TestSDK1或TestSDK2,將ASDK1或ASDK2刪除。
- 方法2,仍通過Pods整合,但ASDK1和ASDK2必須修改為同一Pod標識,整合時顯式指定ASDK版本號。
3. 參考
- 用CocoaPods做iOS程式的依賴管理
- CocoaPods – Class: Pod::Installer
- CocoaPods – pod install vs. pod update
- CocoaPods – Private Pods
相關文章
- iOS 玩轉CocoaPodsiOS
- 玩轉iOS開發《建立CocoaPods開發庫》iOS
- 一起玩轉玩轉LiteOS元件:TinyFrame元件
- 玩轉redisRedis
- 玩轉 pyocd
- 玩轉「Canvas」Canvas
- 玩轉macMac
- 玩轉TCPTCP
- 玩轉RecyclerViewView
- 玩轉cordova
- 玩轉wordpress
- 玩轉SSH埠轉發
- 理解Cocoapods
- 玩轉混合加密加密
- 玩轉EsLintEsLint
- 玩轉 ByteBuffer
- 玩轉策略模式模式
- 玩轉ECMAScript 6 ~
- 玩轉 Laravel HelpersLaravel
- 【iOS】玩轉 - GCDiOSGC
- 玩轉APP支付APP
- 玩轉Docker映象Docker
- 玩轉Windows桌面圖示 (轉)Windows
- 玩轉網頁捲軸(轉)網頁
- 7天玩轉機器學習機器學習
- 玩轉架構之路架構
- Python 玩轉 ExcelPythonExcel
- 玩轉 Bash 變數變數
- transformjs玩轉星球ORMJS
- 玩轉webpack4Web
- 玩轉 React(一)- 前言React
- [譯] 玩轉ptrace (一)
- 玩轉Mysql命令列MySql命令列
- 玩轉模擬物件物件
- 用 JBuiler 玩轉 petstoreUI
- MCTencentOpenAPI Cocoapods支援API
- AlipaySDK Cocoapods支援
- iOS CocoaPods使用iOS