這個部分首先先大概說下pod的一些基本概念~ 然后過一下如果拆分模塊的pod。(這篇也是和同事學習的QAQ)
起源 & Gemfile
在沒有pod之前其實我們是直接拷貝源碼的:

有了pod之后我們可以用pod來引入依賴,避免了手動的繁瑣。pod其實是借鑒Bundler(基于ruby的集成工具,對應(yīng)的是GemFile),cocoapods其實也屬于ruby的一個組件。

所以其實Gemfile和它的lock文件就是鎖死了我們工程所需要的gem環(huán)境,例如哪些ruby的工具,cocoapods的版本、fastlane的版本、所需要的插件們~
原理

我們在podfile里面寫明我們所依賴的庫名,install的時候,pod會從source里面所有的spec repo里面去找到我們要的庫的podspec文件,然后通過這個文件里面的url找到我們的庫,再download下來。
pod setup做的事情其實就是把遠端的podspec文件們都clone到本地。
pod update和pod install的區(qū)別?
pod install如果你不改podfile,那么每次都是一樣的;但是pod update它會先執(zhí)行pod repo update把repo拉一下,如果庫升級了,那么會就去下載最新的庫,然后更新.lock文件里面的版本。pod update還可以升級某個指定的庫~
Pod命令解析過程

-
命令分析就是解析我們輸入的例如
pod install命令 -
依賴解析算法就類似我們會在podfile里面規(guī)定很多依賴的庫,但這些庫也會依賴別的庫,pod里面規(guī)定的其實是一個子集,如何保證引用的庫不會產(chǎn)生版本沖突,就是這個模塊負責檢查的(例如A依賴1.0的B,C依賴2.0的B)
P.S 編譯的時候會先編譯最底層被依賴的庫,例如A依賴B,那么就會先編譯B生成B的.a文件,然后在編譯A - 工程生成模塊其實就是生成那個小白色的工程文件噠(Pods會生成一個工程,我們原工程也有一個工程,所以這個xcworkspace是為了組織這兩個工程)
Pod文件

Podfile.lock是第一次install生成的文件(如果當前木有l(wèi)ock文件),除非podfile變化或者執(zhí)行了pod update否則是不會變的。
它記錄了需要被安裝的 pod 的每個已安裝的版本,當團隊中的某個人執(zhí)行完pod install命令后,生成的Podfile.lock文件就記錄下了當時最新Pods依賴庫的版本,這時團隊中的其它人check下來這份包含Podfile.lock文件的工程以后,再去執(zhí)行pod install命令時,獲取下來的Pods依賴庫的版本就和最開始用戶獲取到的版本一致。
如果沒有Podfile.lock文件,后續(xù)所有用戶執(zhí)行pod install命令都會獲取最新版本的依賴庫,這就有可能造成同一個團隊使用的依賴庫版本不一致。
由于sandbox,也就是pods目錄是不由git管理的,那么怎么知道要不要更新本地庫呢?在每次pod install的結(jié)束的時候,會自動復制一份Podfile.lock復制到Manifest.lock。每次build的時候會執(zhí)行xcode里面設(shè)置的腳本,比較Podfile.lock和Manifest.lock的md5,如果不一致就會報錯the sandbox is not in sync with the podfile.lock. run 'pod install' or update your cocoapods。
每個庫都會生成一個.a的framework文件,pods的project會依賴這些.a文件,然后pods的project也會生成一個總的.a文件,我們自己的porject會引用pods的.a文件:

headers這個目錄就是所有組件對外public的頭文件~ 并且生成xcode的時候會自動在xcode的build settings增加這個search path。
repos文件夾其實是為了防止每次庫依賴分析以及install都去訪問github的spec,所以在本地clone了一個~ 由于外網(wǎng)pod更新非常頻繁,所以有些公司都是自己做的內(nèi)網(wǎng)映射,保證源不會經(jīng)常更新,避免經(jīng)常pod update。如果遇到報錯找不到某個版本,但是git上是有的,執(zhí)行以下pod repo update更新一下源即可。
cache是每次pod install的庫文件的cache,如果其他工程也恰好需要同樣的版本,就可以直接拿copy給它用啦,避免了下載的操作。
P.S. 一個版本的
~>只是末位可以大于,前面的數(shù)字還是要保持一致的,例如1.0.2 ~> 1.0.1,但是1.1.2 ~> 1.0.1是不成立的。
Podfile黑技巧

podfile里面可以通過類似key-value的方式設(shè)置一些值~
clean的意思就是install的時候,如果有些庫沒有用到會清理;share_schemes_for_development_pods是不是把pod target設(shè)置為share;generate_multiple_pod_projects是將pod生成多個project,工程可以動態(tài)檢索文件,這樣每個pod都是一個project,在build的時候就會動態(tài)獲取文件,避免了向本地dev pod增加文件,但是編譯的時候找不到文件,還必須要pod install以后才可以;incremental_installation是多project的模式下增量install,當pull代碼以后podfile可能會有改變,加入這個參數(shù)以后會cache上次的install結(jié)果,只有cache版本不一致才會重新走install(下載 & 生成pod target)的流程。
如果有多個source,然后都有同一個庫,版本號還一致,但是庫實際文件不一樣,那么pod會按順序找到第一個版本拿到然后用,所以不同source如果同一個庫內(nèi)容不一樣但版本號還一樣就容易出bug。
hook
pre_install和post_install也就是pod的開始以及結(jié)束,是可以用腳本注入做一些事情的。podfile其實就是一個ruby腳本,可以在里面做一些hook。

Podfile的編寫

spec的外部引用就是通過path、git、commit之類描述的依賴,也就是除了用版本號規(guī)定的都是,它會根據(jù)文件里面找到的版本號加到版本分析的樹里面~
subspec的意思就是只依賴AFNetworking里面的NSURLSession這個小一點的模塊。
Podspec文件編寫 —— 生成自己的庫

具體代碼如何做參考這個吧:https://zhuanlan.zhihu.com/p/37843887 & http://www.itdecent.cn/p/1dabeb10c33a
關(guān)于本地私有庫可以這么做:https://www.cnblogs.com/hs-funky/p/6759977.html
用本地庫的方式就是在項目內(nèi)建一個文件夾,用于放各個模塊的代碼(如果之前xcode對這些文件有索引可以刪掉),然后給他們按照上面的文章里面生成pod(pod spec create 模塊名),然后編寫pod spec文件,之后修改本項目的podfile,引用這個本地庫通過path的方式,最后pod install,這個時候xcode是沒有這個庫里面的文件的索引的,只有pod有,你會在Development Pods里面看到這個模塊,你也可以修改它然后提交也木有問題(因為其實如果你show in finder會發(fā)現(xiàn)其實就在你最開始建的文件夾里面)~

小優(yōu)化
- Q1: 我們?nèi)绻_發(fā)的時候,需要先改
podfile把自己要改的模塊的庫的path指向本地,然后執(zhí)行pod install,然后修改本地的代碼調(diào)試并提交測試,測試通過以后,將庫推上去,然后打tag,podfile還原用tag來指明庫依賴。
A1: 現(xiàn)在我們公司是可以直接add某個庫成為dev pod,然后自動就會把podfile里面的依賴改為本地,并把這個庫clone到單獨的文件夾讓我們修改。
- Q2: 很多依賴的庫在github上面,并且引入的庫越多,其實編譯的代碼就越多,github拉取還很慢。
A2: 把三方庫都打成靜態(tài)庫,然后放在公司內(nèi)部倉庫,每次install直接從內(nèi)網(wǎng)拉取靜態(tài)庫文件,這樣減少了傳輸時間也減少了編譯時間。
- Q3: 一份代碼,多個target,多個編譯schema,但是對應(yīng)不同的庫依賴怎么辦呢,比如target A需要某個庫但是target B不需要?

- Q4: 如何把主工程定義的宏同步到pod?
A4: 在install的時候為pod添加宏,也就是hook一下pre_install or post_install
