說起 iOS 開發的包管理,大家就不由得會想起 CocoaPods, 它確實是一個強大的工具。但這次咱們來關注另外一個包管理工具 Carthage,如果說 CocoaPods 像一個航母,一應俱全,堅實穩固。那么 Carthage 就像一艘巡洋艦,機動靈活,攻擊迅速。
Carthage 和 CoaoaPods 的區別
CoaoaPods 是一套整體解決方案,我們在 Podfile 中指定好我們需要的第三方庫。然后 CocoaPods 就會進行下載,集成,然后修改或者創建我們項目的 workspace 文件,這一系列整體操作。
相比之下,Carthage 就要輕量很多,它也會一個叫做 Cartfile 描述文件,但 Carthage 不會對我們的項目結構進行任何修改,更不多創建 workspace。它只是根據我們描述文件中配置的第三方庫,將他們下載到本地,然后使用 xcodebuild 構建成 framework 文件。然后由我們自己將這些庫集成到項目中。Carthage 使用的是一種非侵入性的哲學。
所謂非侵入性哲學,其實可以這么理解。我想使用過 CocoaPods 的同學們,可能都會經歷過這樣一種體驗,尤其是在最開始使用它的時候 - 我們精心在 Podfile 中配置好我們所需的第三方庫,並且按照 CocoaPods 的指定步驟,輸入命令,然后等待這些第三方庫乖乖的集成到項目中。但總有那么幾次,會事與願違,比如運行完 pod update 命令,看似一切順利,workspace 也成功的更新了。但當我們真正編譯構建項目的時候,某些莫名其妙的錯誤出現了,類似於這種:
diff: /../Podfile.lock: No such file or directory
diff: /Manifest.lock: No such file or directory
遇到這種問題后,我們只能經過一系列的搜索,然后解決這些問題。本來我們使用包管理,就是為了集成第三方庫的時候更加方便,迅速。結果處理這些包管理的錯誤卻又浪費了我們很多時間。
如果使用 Carthage 我們就不必讓這些問題困擾了,因為 Carthage 本身不會對我們的項目結構進行任何改動,類似 CocoaPods 產生的這些附加問題,就不會發生了。
但是 Carthage 就沒有 CocoaPods 的集成操作能力了,作為開發者,必須在 Carthage 將第三方庫構建完成后,手動的關聯到項目中。
另外 Carthage 除了非侵入性,它還是去中心化的,它的包管理不像 CocoaPods 那樣,有一個中心服務器(cocoapods.org),來管理各個包的元信息,而是依賴於每個第三方庫自己的源地址,比如 Github。這樣也是有利有弊,好處就是我們對包管理不再依賴中心服務器,不會受中心服務器信息量和穩定性的限制(尤其是在我們這里的網絡訪問狀況問題),弊端嘛,就是我們想查找第三方庫的時候,也沒有一個中心服務器來幫助我們進行索引,而是必須從網絡上自行查找。
兩種哲學,產生了兩個產品 Carthage 和 CocoaPods 各有優劣,如何選擇,就要看各位自己的需求了。
開始使用 Carthage
Carthage 的基本情況介紹完了,接下來咱就來看一下怎樣使用 Carthage 來進行包管理吧。
首先我們需要安裝 Carthage 環境,可以在它的 Github 主頁上,找到下載地址:https://github.com/Carthage/Carthage/releases:
Carthage 目前最新版本是 0.9.3
,下載 Carthage.pkg
包就可以,下載成功后,雙擊安裝。
安裝成功后,我們就可以在項目中配置 Cartfile
文件了,可以在我們項目的根目錄中,使用任何一個你熟悉的文件編輯器,建立這個文件:
$ vim Cartfile
在 Cartfile
文件中,引入一個第三方庫,比如 SwiftyJSON
:
github "SwiftyJSON/SwiftyJSON"
然后我們保存文件,回到命令行界面,再次輸入命令:
$ carthage update
緊接着,Carthage
就會開始抓取並使用 xcodebuild 構建第三方庫:
*** Cloning SwiftyJSON
*** Checking out SwiftyJSON at "2.3.0"
*** xcodebuild output can be found in /var/folders/08/sys7159s6zjfd52t3p35qrbc0000gq/T/carthage-xcodebuild.yqDOKU.log
*** Building scheme "SwiftyJSON OSX" in SwiftyJSON.xcworkspace
*** Building scheme "SwiftyJSON iOS" in SwiftyJSON.xcworkspace
*** Building scheme "SwiftyJSON watchOS" in SwiftyJSON.xcworkspace
update
操作完成后,會在項目的根目錄中生成一個 Carthage 目錄。這個目錄中又包含了兩個目錄 Build 和 Checkout。
Build 中存放的是構建好的 framework 包:
Checkouts 中存放的是簽出的第三方庫項目源文件:
接下來,我們回到項目設置,進入 General 選項卡,在最下方的 Linked Frameworks and Libraries 中,將 Carthage/Build/iOS 中的 framework 文件添加到項目中:
然后在 Build Phrases 中,點擊左上角的 + 號,添加一個 New Run Script Phrase:
然后在腳本區域輸入:
/usr/local/bin/carthage copy-frameworks
最后將 SwiftyJSON 的路徑添加到 Input Files 中。
$(SRCROOT)/Carthage/Build/iOS/SwiftyJSON.framework
最終結果如下:
添加這個 Run Script 的作用是為了讓運行時能夠找到這個動態庫。這點 Carthage 官方文檔中沒有太明確的說明。我實際的實驗過,如果不添加這個 copy-frameworks
腳本,那么項目在運行的時候會因為找不到這個動態庫而在啟動的時候崩潰。
還可以將 Carthage
所集成的第三方庫生成的符號文件添加到項目中,這樣我們在調試的時候,就可以步入第三方庫內部的代碼啦。
具體步驟,還是進入 Build Phrases ,然后在右上角點擊 New Copy Files Phrase,然后將 Carthage/Build/iOS 目錄中的 SwiftyJSON.framework.dSYM 符號文件拖動進來:
這樣,我們項目運行后,就可以在斷點中步入 SwiftyJSON 內部的代碼啦。
關於這個符號文件,還有一點大家要注意的,如果你使用的是 Xcode 7 以上的版本,有可能在加入了符號文件后,造成編譯出錯。那么可能是因為一個構建選項引起的。
這時,可以在 Build Settings 中,找到 Strip Debug Symbol During Copy 這個選項,確保這個選項的值設置為 NO。
然后再重新編譯,一般就可以正常通過了。這個編譯選項是指定在 Copy 符號文件的時候是否對符號表進行處理,在新版的 Xcode 上這個選項默認是 YES 的,所以咱們需要把它設置為 NO。這個問題也是官方文檔中沒有提到的,我在調試的時候,遇到過這個問題,經過一番搜索才找到原因,困擾了我好半天~
好啦,經過一番折騰,我們通過 Carthage 將 SwiftyJSON 庫順利的集成到項目中啦。
水平有限,這里也只是對 Carthage 進行了初步的介紹。希望借助這個文章,與大家進行一個交流分享,希望能夠作為拋磚引玉,相信屏幕前的你有着更多的聰明才智,也歡迎大家一起討論自己更深入研究的經驗。
如果你讀了這篇文章還意猶未盡的話,在我們的微信公眾平台上還有更多關於包管理的討論,關注公眾號 "swift-cafe" 然后發送 "包管理" 即可查看。
Carthage 在 GitHub 上的主頁:https://github.com/Carthage/Carthage