本文由 伯樂在線 - programmer.du 翻譯自 Michele Titolo。歡迎加入技術翻譯小組。轉載請參見文章末尾處的要求。
html
Cocoapods是 OS X 和 iOS 下的一個第三方庫管理工具。你能使用CocoaPods添加被稱做「Pods」的依賴庫,並輕鬆管理它們的版本,而不用考慮當前的時間和開發環境。git
Cocoapods意義體如今兩個方面。首先,引入第三方庫無可避免地要進行各類各樣的配置。對於Objective-C的初級開發者來講,項目配置但是一件艱鉅的任務。在配置編譯階段和連接器選項的過程當中,極有可能引入許多人爲的錯誤。而CocoaPods簡化了這一切,它能自動配置編譯選項,拯救了開發者。xcode
其次,使用CocoaPods能夠很方便地查找新的第三方庫。固然,這可不是說讓你七拼八湊別人代碼而開發出一個「移栽」應用。而是讓你找到真正好用的庫,縮短你的開發週期,提高你的代碼質量。緩存
接下來,咱們將經過分析pod安裝的過程,一步步揭示CocoaPods背後的技術。ruby
CocoaPods是用ruby寫的,並劃分紅了若干個Gem包。CocoaPods在解析執行過程當中最重要的幾個包的路徑分別是:CocoaPods/CocoaPods、 CocoaPods/Core 和 CocoaPods/Xcodeproj。markdown
CocoaPods / CocoaPodapp
這是面向用戶的組件,每當你執行一個pod命令時,這個組件將被激活。它包括了全部實用CocoaPods的功能,而且還能調用其餘gem包來執行任務。ide
CocoaPods / Core工具
Core gem提供了與CocoaPods相關的文件(主要是Podfile和podspecs)的處理。post
Podfile
Podfile用於配置項目所須要的第三方庫。它能被高度定製,因此你能夠儘量地給它添加你想要的特性。若是您還想對Podfile瞭解更多的話,請查看Podfile指南(地址 http://guides.cocoapods.org/syntax/podfile.html)。
Podspec
.podspec文件描述了一個庫將怎樣被添加進工程中。.podspec文件能夠標識該第三方庫所須要的源碼文件、依賴庫、編譯選項,以及其餘第三方庫須要的配置。
CocoaPods / Xcodeproj
這個包負責工程文件直接關係的處理。它能建立以及修改.xcodeproj文件和.xcworkspace文件。它也能夠做爲一個獨立的包使用,當你要編寫修改項目文件的腳本時,能夠考慮使用CocoaPods/Xcodeproj。
pod install的執行引起了不少操做。瞭解底層運行過程最簡單的方式就是給pod install語句添加 –verbose 參數。如今,運行
pod install --verbose
將會出現如下執行結果:
Analyzing dependencies Updating spec repositories Updating spec repo `master` $ /usr/bin/git pull Already up-to-date. Finding Podfile changes - AFNetworking - HockeySDK Resolving dependencies of `Podfile` Resolving dependencies for target `Pods' (iOS 6.0) - AFNetworking (= 1.2.1) - SDWebImage (= 3.2) - SDWebImage/Core Comparing resolved specification to the sandbox manifest - AFNetworking - HockeySDK Downloading dependencies -> Using AFNetworking (1.2.1) -> Using HockeySDK (3.0.0) - Running pre install hooks - HockeySDK Generating Pods project - Creating Pods project - Adding source files to Pods project - Adding frameworks to Pods project - Adding libraries to Pods project - Adding resources to Pods project - Linking headers - Installing libraries - Installing target `Pods-AFNetworking` iOS 6.0 - Adding Build files - Adding resource bundles to Pods project - Generating public xcconfig file at `Pods/Pods-AFNetworking.xcconfig` - Generating private xcconfig file at `Pods/Pods-AFNetworking-Private.xcconfig` - Generating prefix header at `Pods/Pods-AFNetworking-prefix.pch` - Generating dummy source file at `Pods/Pods-AFNetworking-dummy.m` - Installing target `Pods-HockeySDK` iOS 6.0 - Adding Build files - Adding resource bundles to Pods project - Generating public xcconfig file at `Pods/Pods-HockeySDK.xcconfig` - Generating private xcconfig file at `Pods/Pods-HockeySDK-Private.xcconfig` - Generating prefix header at `Pods/Pods-HockeySDK-prefix.pch` - Generating dummy source file at `Pods/Pods-HockeySDK-dummy.m` - Installing target `Pods` iOS 6.0 - Generating xcconfig file at `Pods/Pods.xcconfig` - Generating target environment header at `Pods/Pods-environment.h` - Generating copy resources script at `Pods/Pods-resources.sh` - Generating acknowledgements at `Pods/Pods-acknowledgements.plist` - Generating acknowledgements at `Pods/Pods-acknowledgements.markdown` - Generating dummy source file at `Pods/Pods-dummy.m` - Running post install hooks - Writing Xcode project file to `Pods/Pods.xcodeproj` - Writing Lockfile in `Podfile.lock` - Writing Manifest in `Pods/Manifest.lock` Integrating client project
整個過程當中執行了不少操做,不過把它們分解以後,會發現它們都很簡單。讓咱們逐步來分析。
閱讀Podfile文件
你是否吐槽過Podfile的語法太過詭異,其實這是ruby的語法而不是OC。相較而言,Podfile要比現有的其餘格式更加簡單好用一些。
安裝的第一步是要弄清楚哪些第三方庫被顯式或隱式地聲明瞭。CocoaPods加載podspecs文件時,獲取了第三方庫的名稱及版本列表。Podsspecs文件存儲在本地,路徑爲~/.cocoapods。
版本控制和衝突
CocoaPods使用語義版本命名約定來解決對版本的依賴。因爲衝突解決系統創建在非重大更改的補丁版本之間,這使得解決依賴關係要容易得多。舉個栗子,兩個徹底不一樣的第三方庫同時依賴CocoaLumberjack。它們其中一個依賴的版本是2.3.1,而另外一個則爲2.3.3,解析器能夠自動使用較新的版本,在這裏則是2.3.3,由於這能夠與2.3.1向後兼容。
但這並不老是有效。有許多第三方庫還並不支持這個約定,這讓解決方案變得很是複雜。
固然,老是會有一些衝突須要手工解決。若是一個第三方庫依賴CocoaLumberjack 1.2.5,而另外一個依賴CocoaLumberjack 2.3.1,最後只能靠調用這兩個第三方庫的用戶來手動地決定CocoaLumberjack的版本了。
加載源碼
CocoaPods執行的下一個步驟是加載源代碼。每一個.podspec文件都包含了源代碼的索引,這些索引通常指向了一個git地址或者git tag。它們以commit SHA碼的方式存儲在 ~/Library/Caches/CocoaPods中。而在這些路徑中建立文件則由 Core 包負責。
源代碼將依照Podfile、.podspec和緩存文件的信息下載到相應的第三方庫路徑。
生成Pods.xcodeproj
每次pod install 執行後而且檢測到改動時,Pods.xcodeproj文件將唄Xcodeproj gem更新。若是Pods.xcodeproj文件不存在,則會以默認配置生成,若已存在,則Pods.xcodeproj會使用現有的配置。
安裝第三方庫
當Cocoapods向項目中增長了一個第三方庫的時候,不只僅是將添加代碼這麼簡單。因爲每一個第三方庫有不一樣的target,因此每次添加第三方庫時,都只有幾個文件被添加。每一個源代碼都須要:
一旦每一個pod的target都完成了以上步驟,整個Pods的Target就會被建立。這增長了相同的文件,與另外幾個。若是有源代碼中包含了資源bundle,向app的target中添加bundle的方式將寫入Pods-Resources.sh。還有一個叫Pods-environment.h的文件,文件中含有許多檢查組件是否來自pod的宏定義。最後,將生成兩個確認文件,一個.plist文件,一個用於給用戶查閱許可信息的markdown文件。
寫入到磁盤
直到如今,許多已完成的過程都使用的是內存中的對象。爲了讓這些過程的結果可重複被使用,咱們須要將全部結果都記錄在一個文件中。因此Pods.xcodeproj和另外兩個很是重要的文件:Podfile.lock和Manifest.lock都將被寫入磁盤。
Podfile.lock
這是CocoaPods建立的最重要的文件之一。它記錄了須要被安裝的pod的每一個已安裝的版本。若是你想知道已安裝的pod是哪一個版本,能夠查看這個文件。推薦將Podfile.lock文件加入到版本控制中,這有助於整個團隊的一致性。
Manifest.lock
這是每次運行pod install時建立的Podfile.lock文件的副本。若是你見過「沙盒文件和Podfile.lock文件不一樣步」的錯誤,這個錯誤就是因Manifest.lock文件和Podfile.lock文件不同引發。因爲Pods所在的目錄並不總在版本控制之下,這樣能夠保證開發者運行app以前都能更新他們的pods,不然app可能會crash,或者在一些不太明顯的地方編譯失敗
xcproj
若是您已經依照咱們的建議在系統上安裝了xcproj,它會將您的Pods.xcodeproj文件轉換成就舊有ASCII格式的plist文件。爲何要這麼作呢?由於Xcode所依賴和使用的plist在好久之前就已經不被其餘軟件支持了。若是沒有xcproj,你的Pods.xcodeproj文件將會以XML格式的plist文件存儲,當你用Xcode打開它時,它會被改寫,形成大量的文件衝突。
運行pod install的最終結果是許多文件被添加到你的工程和系統中。這個過程一般只須要幾秒鐘。固然沒有Cocoapods這些事也均可以完成。只不過所花的時間就不只僅是幾秒而已了。
CocoaPods和持續集成在一塊兒很是融洽。雖然持續集成很大程度上取決於你的項目配置,但Cocoapods依然能很容易地對項目進行編譯。
Pods文件夾已加入版本控制的持續集成
若是包括Pods文件夾的一切東西都在版本控制之中,那麼你不須要特別作什麼就可以持續集成。因爲編譯時必須指定一個scheme,因此只須要保證使用了正確的scheme便可。
沒有Pods文件夾的持續集成
若是你的Pods文件夾沒有被歸入版本控制之中,那麼你須要一些額外的步驟來保證持續集成的順利進行。最起碼,Podfile文件要放入版本控制之中。另外強烈建議將生成的.xcworkspace文件和Podfile.lock文件歸入版本控制,這樣不只簡單方便,更能保證所使用的Pod是正確的版本。
一旦配置完畢,讓CocoaPods在CI上正確運行的關鍵是保證每次編譯以前都執行了pod install。在大多數系統中,譬如Jenkins或者Travis,你只用把「pod install」定義爲一個編譯步驟便可(實際上,Travis會自動執行pod install)。隨着Xcode Bot的發佈,咱們尚未找到能像書寫的這麼流暢的解決方案,不過咱們正朝着解決方案努力,一旦成功,咱們將會當即分享。
CocoaPods簡化了OC的開發流程,咱們的目標是讓第三方庫更容易被發現和添加。瞭解CocoaPods的原理能讓你作出更好的App。咱們沿着CocoaPods的整個流程一步步執行,從載入specs文件和源代碼、建立.xcodeproj文件和全部組件到將全部文件寫入磁盤。因此接下來,咱們運行 pod install –verbose,靜靜觀察CocoaPods的魔力如何顯現。