CocoaPod 與 Git 元件化相關細節
前言
隨著專案的發展, 元件化幾乎是一個必然的過程, 而使用 Git + CocoaPod 來管理元件是目前業界主流方式.
使用 Pod 來管理元件的優勢是非常明顯的, 網路上一些文章說的非常清楚, 個人最看重的是以下三點:
- 從根本上解決混亂引用導致的強耦合問題.
- 每個 Pod 可以獨立維護, 獨立單元測試, 單獨走 Git Flow 流程.
- 穩定的元件可以打包成靜態庫加快編譯速度.
但也需要知道, 元件化會帶來一系列缺點, 而這些缺點你在網上一般找不到:
- 學習成本, 使用 Pod 與 Git 來管理元件可能會遇到一般使用 Pod 沒有遇到的各種問題, 這種採坑成本是不能忽略的.
- 使用 Pod 管理元件無疑會拉長每個開發人員的開發流程, 提高開發成本.
- 當元件的邊界不清晰或者元件還沒有非常穩定的時候, 反覆修改真的很浪費時間.
- 元件化依賴很好的 App 架構, 開發人員也需要有一定的架構思想, 什麼時候需要通過路由轉發訊息, 什麼時候做成獨立SDK, 層級之間的依賴, 都是需要思考的問題.
- 元件化之後, 每次合併程式碼衝突是亂七八糟, 往往一個 pod install 便帶來幾百個衝突, 適應並解決這種問題也是一種成本.
- 開發的元件一定要足夠封裝足夠聚合, 否則 Pod 與主工程中各種強依賴耦合是災難性的.
雖然元件化有種種不是, 但就像一個公司大了, 必須要有各種規範流程一樣, App大了, 開發人員多了, 元件化就如同 Git Flow 流程一樣, 麻煩但免去了很多問題.
一些檔案
元件化涉及到的東西還真不少, 以下會提到一些檔案, 可能你已經很熟悉, 但使用 Cocoapod 管理元件之後, 你將於他們打交道的更多, 下面記錄一些與之相關的細節.
podfile:
都知道這個檔案的作用, 如果你只用 pod 管理第三方庫 , 你可以直接使用一個普通模板 podfile, 新增第三方庫, 安裝即可, 但管理元件則需要對這個更熟悉, 這是管理元件的根本, 以下說說一些注意點:
- use_frameworks!: 通個關鍵詞生成的是 framework 而不是靜態庫, 很直觀的就是 podfile 中加上這個, 在主工程中使用<>引用就要使用路徑, 不加則可以直接引用標頭檔案.
- inhibit_all_warnings!: 隱藏所有 pod 中的告警, 這個挺有用的, 加快編譯速度.
- 所有的 pod 都須指向 tag, 可以避免很多問題.
- source: 指定源, 第一個源應該是私有源, 後面才是官方源, 這樣若出現同名的 pod 會優先載入私有源中的, 方便映象第三方庫.
- def end語法: 用法很簡單, 就像巨集命令一樣, 但不支援駝峰標識.
- :configurations = 'Debug': 只在 debug 環境載入, 對應的關鍵詞是 'Release'.
- 每個元件一定要寫好註釋, 否則你同事看到的時候一定是懵逼的.
podfile.lock:
當我們執行 pod install 命令時, 工程中的 pod 就會更新到 podfile.lock 中的版本, 這個是讓我們在多人協作中避免第三方庫的版本不同的檔案, 但是不可避免的我們元件化之後會執行 pod update, 而每次 pod update 都會更新這個檔案, 所以這個檔案的作用便顯得有些雞肋了, 也正是因為這樣, podfile 中的各個 pod 應該指明 tag, 否則便是災難. 而且某些特殊的需求, 我們可能會需要切換 pod 的 tag, 也因這個檔案的存在, 使用 pod install 便會報錯, 只能使用 pod update.
manifest.lock:
可以簡單的理解為我們在本地執行一次 pod install 後生成的當前Podfile的狀態的表徵檔案, 一般用來校驗與 podfile.lock 是否一致.
xcconfig:
儲存每一個 pod 的工程配置檔案, 這個檔案很容易在合併程式碼時衝突, 一般可以忽略, pod install 即會重新生成.
project.pbxproj:
記錄工程檔案結構及位置的檔案, 不論有新增、移動或者刪除都會改變這個檔案, 所以這個是必定會衝突的檔案, 再配合上海量的 xcconfig 檔案變動, 讓合併程式碼變得更加困難, 一般的做法是以他人的版本解決問題, 對於主工程中的檔案, 缺少的重新 add file, 對於 pod 中的檔案, 直接 pod install, 再合併.
podspec:
每一個 pod 的配置檔案, 也是元件化的核心檔案, 我們建立的私有源或者官方源本質上就是一個個 pod 名字命名的資料夾, 子資料夾為各個版本號, 最內層就只有一個 podspec 檔案, 這個也是最容易出問題的檔案, 這個檔案的配置方法就不說了, 下面說說這個檔案中的注意點:
- version 問題, 一般來說, 這裡的 version 要等於 git 上的 tag 值.
- source_files 為原始檔.
- public_header_files 為開放的標頭檔案.
- resources 為資源路徑.
- frameworks 依賴的庫, 一般為系統的庫例如 AVFoundation、UIKit等.
- library 依賴的靜態庫, 比如 resolv、c++.
- vendored_frameworks pod 中 .framework 檔案.
- vendored_libraries pod 中的.a 檔案
- dependency 依賴的元件, 會從 podfile 中的 source 去尋找相關 pod, 建議在 podspec 中不要指定版本號, podfile 中統一指定.
- pod_target_xcconfig, 工程中配置的鍵值對.
- subspec, 子 pod, subspec 影響整合後的資料夾結構, 但不要層級太多, 也不要劃分太細, 非常影響編譯速度, 另外 subspec 之間的依賴不是資料夾依賴, 而是 superspec/subspec 這種形式.
一些操作
上面說了一些檔案及其中的細節, 下面說一下常用的操作.
pod lib lint 與 pod spec lint
前者為驗證遠端倉庫與本地倉庫, 後者為僅驗證本地倉庫, 有時候會出現只有一個能通過, 那表明遠端倉庫與本地倉庫沒有完全對應. 常用的引數:
- 允許告警 --allow-warnings.
- 該 pod 有使用靜態庫 --use-libraries.
- 列印詳細log --verbose.
- 自定義源 --source 源地址.
pod repo push 源的地址 podspec檔案
將 podspec 檔案 push 到私有源中. 過程中會經過 pod lib lint 驗證, 後面可以接驗證相同引數.
pod cache clean --all
清除 pod 相關快取, 若遇到一些快取相關的錯誤可以使用, 同時可以使用 pod repo remove 源名稱, 刪除相關本地倉庫.
pod package podspec檔案 --foce / pod package podspec檔案 --library --force
利用 pod package 打包靜態庫. 前者為 .framework, 後者為 .a 檔案.
tag 流程
打 tag 在元件化中是用的最多的流程, 雖然已經有 jinkins 這種工具讓這一步自動實現, 但我們也不能忘了手動 tag 的流程.
首先更新 pod 中的檔案, 及 podspec, 在示例程式中無錯誤後, podspec 中的 version 改為更大的版本號. 操作 git:
- git add .
- git commit -m '描述'
- git push
- git tag -a '版本號' -m '描述'
- git push --tags
再將 podspec 利用上面 repo push 命令推到私有源, podfile 修改對應版本號, pod update 對應pod, 完成了版本的升級. 值得注意的是 git 的 tag 不要刪除, 否則會出現一些快取問題.
待續....