iOS-CocoaPods的原理及Podfile.lock問題
highlight: a11y-dark
背景:
在日常開發中,我們的專案中都會使用到三方庫,並且會選擇使用 CocoaPods 進行管理。這其中我們就會經常遇到關於 podfile.lock 要不要提交,podfile.lock 的作用是幹嘛的以及衝突怎麼解決,pod install 和 pod update 有什麼區別等這些問題
,下面就來詳細介紹下如何解決這些問題。
什麼是 CocoaPods
CocoaPods
是OS X和iOS下的一個第三類庫管理工具,通過CocoaPods工具我們可以為專案新增被稱為Pods
的依賴庫(這些類庫必須是CocoaPods本身所支援的),並且可以輕鬆管理其版本。
CocoaPods的好處
1、在引入第三方庫時它可以自動為我們完成各種各樣的配置,包括配置編譯階段、聯結器選項、甚至是ARC環境下的-fno-objc-arc配置等。
2、使用CocoaPods可以很方便地查詢新的第三方庫,這些類庫是比較“標準的”,而不是網上隨便找到的,這樣可以讓我們找到真正好用的類庫。
關於CocoaPods可以參考這篇文章:https://www.jianshu.com/p/9e4e36ba8574
這篇文章主要用來介紹CocoaPods的原理和使用注意事項。
CocoaPods 整合原理
CocoaPods 的原理是將所有的依賴庫都放到另一個名為Pods的專案中,然而讓主專案依賴Pods專案, 這樣,原始碼管理工作任務從主專案移到了Pods專案中。
js
1.Pods專案最終會編譯成一個名為libPods.a的檔案, 主專案只要依賴這個.a檔案即可.
2.對於資原始檔, CocoaPods提供了一個名為Pods-resources.sh的bash腳步, 該指令碼在每次專案
編譯的時候都會執行,將第三方庫的各種資原始檔複製到目標目錄中.
3.CocoaPods通過一個名為Pods.xcconfig的檔案在編譯設定所有的依賴和引數
js
libPods.a
Pods-resources.sh
Pods.xcconfig
Cocoapods的下載原理
s.source = { :git => '[email protected]:app/iOS-XXX.git', :tag => '1.0.0' }
-
根據:git => ‘[email protected]:app/iOS-XXX.git’找到對應的git倉庫;
-
根據:tag => ‘1.0.0’定位到對應
tag的提交
(如果沒有註明Pod依賴庫版本則定位到最後一次的提交); -
在這次提交中檢索字尾為.podspec的檔案(檔案可以隨便命名),驗證s.name是否與Podfile中的一致;
-
如果不一致則install時會報錯:
[!]Unable to find a specification for ‘React’
。驗證成功後,就會根據Podspec中的s.source_files找到需要匯入的程式碼檔案,並通過其他的的資料找到對應的配置檔案或資原始檔等; -
然後將其下載到本地專案中。
js
注意:
如果是共有庫,這些原理也相同。只是共有庫要將podspec檔案上傳到cocoapods。在匯入的時候通過名字React去cocoapods匹配對應的podspec,然後根據s.source去找到對應的倉庫和對應的版本,然後會再去匹配新的podspec,後邊的步驟就完全相同了。
版本控制原理
當執行完 pod install之後,cocoapods 會生成一個podfile.lock
的檔案。podfile.lock 檔案最大的用處在於多人開發。如果你沒有在podfile中指定pods版本pod ‘React’,那麼預設為獲取當前React依賴庫的最新版本
。
當團隊中的某個人執行完 pod install 命令後,生成的 podfile.lock 檔案就記錄下了當時最新 pods 依賴庫的版本
,這時團隊中的其他人 check 下來這份包含 podfile.lock 檔案的工程以後,再去執行 pod install 命令時,獲取下來的 pods 依賴庫的版本和最開始使用者獲取到的版本一致
。如果沒有podfile.lock檔案,後續所有使用者執行pod install命令都會獲取最新版本的React,這就可能造成一個團隊使用的依賴庫版本不一致,這對團隊協作來說絕對是個災難。在這種情況下,如果團隊想使用當前最新版本的React依賴庫,有兩種方案
:
1、更改podfile,使其指向最新版本的‘React’依賴庫
2、執行pod update命令;鑑於podfile.lock檔案對團隊協作如此重要,所以應該加入到版本控制裡面。
podfile.lock到底要不要提交
podfile.lock檔案是需要提交的。
當我們app元件化之後,一個app會包含各種不同的版本元件,而主工程變成一個殼子,用Podfile檔案依賴了各種不同的元件, 然後我們的app完成了一次版本迭代上線之後,這個時候需要主工程相對應的元件版本,相對應版本的元件又依賴其他版本元件,如果我們手動通過spec管理肯定非常麻煩,又如果我們直接把全部的元件都寫在podfile中,那我們每次的時候回溯
(我們現在在開發2.0版本,想回到1.0版本)的時候,都需要首先記錄之前app版本中對應的全部元件的版本,然後再在podfile中寫上對應的元件版本號,如果元件特別多,需要回溯多次,這樣也是非常痛苦的。那有沒有最簡單一句命令一個執行操作一分鐘一步到位回溯之前
的版本的方法呢?這個時候我們就需要依靠podfile.lock檔案進行版本管理。
Podfile.lock 中會標註專案當前依賴庫的準確版本
,其中包括了專案在 Podfile 中直接標註使用的庫,以及這些庫依賴的其他庫。這樣的好處是當你跟小夥伴協同開發時,你的小夥伴同步了你的 Podfile.lock 檔案後,他執行 pod install 會安裝 Podfile.lock 指定版本的依賴庫,這樣就可以防止大家的依賴庫不一致而造成問題。因此,CocoaPods 官方強烈推薦把 Podfile.lock 納入版本控制之下。
所以如果我們用 Podfile.lock 檔案進行版本管理,只需要在主工程(就是那個殼子)中把Podfile.lock 納入版本控制之下(也就是把主工程對應的 Podfile.lock檔案上傳到gitlab
),並且主工程中的 Podfile檔案一定不要指定版本號, 然後把app 每次封版本的時候在gitlab打上相應的版本號tag,每次我們想回溯之前版本 只需要切換到當時的tag,然後執行 pod install (千萬不能執行 pod upodate,因為執行完 pod upodate 對應的 Podfile.lock 裡面的庫版本會跟著更新
)就可以了就是這麼簡單。
podfile.lock衝突的解決
```js diff: /../Podfile.lock: No such file or directory
diff: Manifest.lock: No such file or directory
error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.` ```
平常開發過程中,專案在執行完 pod install 後提示 Podfile.lock 檔案被修改,需要提交。但是其他同事(同事電腦的pod版本和你的不一致)拉下來程式碼後,執行專案發現了這個錯誤,然後執行 pod install ,解決了這個問題,然後再提交了 Podfile.lock 檔案。等你再更新程式碼發現也出現了這個問題,這就會陷入一個死迴圈。而我們又不能不提交 Podfile.lock 檔案,所以這個問題的解決版本就是將大家電腦的pod版本號保持一致
。
```js 刪除舊版本號 sudo gem uninstall -n /usr/local/bin cocoapods -v XXX
安裝新版本號的pod sudo gem install -n /usr/local/bin cocoapods -v XXX ```
Pod install 和 Pod update的區別
```js pod install:用於第一次為專案下載pods,還有後續增加或者刪除庫的時候。
pod update: 用於更新庫的版本。會遍歷所有的庫進行更新,並更新 Podfile.lock 檔案。
pod update name: 只會更新指定的庫。
pod repo update: 更新整個.cocoapods下的所有庫的配置檔案,挨個檢查對應的框架有沒有新版本釋出,有的話更新本地的資源配置檔案.
pod install --no-repo-update:根據podfile檔案或者podfile.lock下載並匯入對應的第三方庫,跳過檢查資源配置檔案是否需要更新的環節 ```
使用示例
示例1:專案需要依賴A、B、C
三個庫,當前三個庫的版本都是1.0.0,建立 Podfile 檔案,執行Pod install
。會拉取這三個庫,並且Podfile.lock
中 A、B、C 的版本都會鎖定為1.0.0。
示例2:專案需要增加一個 pod D,在 Podfile 檔案中引入D,這裡應該使用 pod install。因為只是想增加D,而不想更新其他三個庫。
示例3:這時假如團隊其他成員加入這個專案,克隆了專案倉庫,然後執行 'pod install'。由於Podfile.lock被提交了,所以能確保新成員使用的庫版本和我的是一樣的。即使 pod A 有'1.1.0' 版本可以使用,因為 Podfile.lock中鎖定的Pod A的版本是1.0.0。
示例4:檢查版本更新,如果想更新 pod A到1.1.0版本,而 pod B也有新版本但是不想更新 pod B,這個時候就使用 pod update A就可以了,這個時候 Podfile.lock 中 pod B的版本資訊也會更新。
注意:使用固定版本的 Podfile,例如 pod 'A', '~> 1.1.0',這樣是不是可以確保專案中的所有成員使用的都是同一個版本?答案是否定的,當在執行 pod update時,只能保證'A'的版本是固定的,但是如果'A'還依賴 pod A1,甲同學拉取的時候A1版本為1.0.0,而當乙同學拉取時 pod A1 最新版本是 '1.1.0' 版本了,就會導致A1的版本為 '1.1.0' 了。這就是為什麼確保團隊每個成員使用在不同電腦使用同一版本的唯一方式時使用 Podfile.lock 並且適當使用 pod install 和 pod update 。
版本號的邏輯關係
js
'> 0.1' --- 版本號大於0.1的
‘>= 0.1’ --- 版本0.1和版本號大於0.1的
'< 0.1' --- 版本號小於0.1的
‘<= 0.1' --- 版本號0.1和版本號小於0.1的
版本號的最優匹配
js
‘~> 0.1.2' --- 版本0.1.2和版本號處於0.1.2-0.2之間的,不包括0.2和更高版本
‘~> 0.1' --- 版本0.1和版本號處於0.1-1.0之間的,不包括1.0和更高版本
‘~> 0' --- 版本0和更高,和沒設沒啥區別
總結
本文介紹了git提交是podfile.lock
要不要提交,podfile.lock 的作用是幹嘛的以及衝突怎麼解決。pod install 和 pod update 有什麼區別。
參考文章:
https://www.jianshu.com/p/52c5035c9a87
https://www.jianshu.com/p/2dc97f9a6989?utm_campaign=maleskine
- Flutter:仿京東專案實戰(4)-購物車頁面功能實現
- Flutter整合原生遇到的問題彙總
- Flutter:仿京東專案實戰(3)-商品詳情頁功能實現
- Flutter-Dart中的非同步和多執行緒講解
- iOS-底層原理分析之Block本質
- Flutter-官方推薦的Flutter與原生互動外掛Pigeon
- Flutter-flutter_sound錄音與播放
- iOS-CocoaPods的原理及Podfile.lock問題
- iOS配置多環境的三種方案
- iOS-各種Crash防護
- iOS-Swift中常見的幾種閉包
- Flutter:仿京東專案實戰(2)-分類和商品列表頁面功能實現
- Flutter:仿京東專案實戰(1)-首頁功能實現
- Flutter-JSON轉Model的四種便捷方案
- Flutter-導航與路由堆疊詳解
- Flutter 與原生通訊的三種方式
- iOS-記憶體洩漏檢測
- Fastlane實現自動打包
- 懶人必備神器-Xcode程式碼塊
- Jenkins實現自動化打包