項(xiàng)目組件化、平臺化是技術(shù)公司的共同目標(biāo),越來越多的技術(shù)公司推崇使用pod管理第三方庫以及私有組件,一方面使項(xiàng)目架構(gòu)更加清晰,一方面現(xiàn)有的工具Cocoapods提供了近乎完美的解決方案。這里我們來討論一下如何在Xcode 工程中集成Cocoapods,這里提供入門級別的集成和進(jìn)階集成方式。
本文目錄
參考文檔匯總
- Cocoapods官網(wǎng):https://cocoapods.org/
- Cocoapods在github上的開發(fā)倉庫:https://github.com/CocoaPods/CocoaPods
- Cocoapods 錯誤匯總 https://github.com/CocoaPods/CocoaPods/issues
- Cocoapods幫助界面http://guides.cocoapods.org/using/using-cocoapods.html
- Cocoapods入門參考文檔:http://www.tuicool.com/articles/RzI3ye
- 創(chuàng)建私有pod參考文檔: http://www.cocoachina.com/ios/20150228/11206.html
- 私有Pods: http://blog.wtlucky.com/blog/2015/02/26/create-private-podspec/
- 淘寶技術(shù)架構(gòu):http://blog.cnbluebox.com/blog/2014/03/31/cocoapodsdai-ma-guan-li/
項(xiàng)目中配置Cocoapods解決方案
Cocoapods簡介
Cocoapods是OS X和iOS下的一個第三方庫管理工具,并且支持Objective-C和swifit語言。通過Cocoapods為項(xiàng)目添加稱為"Pods"的依賴庫(這些庫必須是Cocoapods所支持的),并且輕松實(shí)現(xiàn)第三方庫的版本管理。
引入Cocoapods的意義:
Cocoapods在引入第三方庫時自動為我們完成各種配置,包括配置編譯階段、連接器選項(xiàng)、甚至是ARC環(huán)境下的-fno-objc-arc配置等
Cocoapods可以很方便的查找第三方庫,可以快速方便的尋找到優(yōu)秀的第三方庫以及它們的各種信息。
Cocoapods 官方網(wǎng)站:
Cocoapods整個項(xiàng)目托管在github上, 所有的Pods依賴庫也都依賴github
Cocoapods發(fā)展背景
Cocoapods創(chuàng)建于2011年,目前Cocoapods團(tuán)隊(duì)有17位核心開發(fā)人員以及多達(dá)5000多個開源項(xiàng)目。Cocoapods的存在為代碼分發(fā)提供了非常便捷的解決方案。
Cocoapods核心組件
Cocoapods是用Ruby寫的,所以在安裝時有時要更新ruby源。Cocoapods在解析過程中最重要的幾個包的路徑分別是:CocoaPods/CocoaPods、 CocoaPods/Core和 CocoaPods/Xcodeproj,其中Core提供了CocoaPods相關(guān)文件,主要是podfile和podspecs。
podfile:該文件用于配置項(xiàng)目所需的第三方庫,可以被高度訂制。
podspec:該文件描述一個庫如何被加入到工程文件中。.podspec文件可以標(biāo)識該第三方庫所需要的源碼文件、依賴庫、編譯選項(xiàng),以及其他的第三方庫所需的配置。
over.
Cocoapods與項(xiàng)目sdk化
有些項(xiàng)目處于某些模塊采取的是將該業(yè)務(wù)代碼打成framework,如比較重要的金融支付模塊。我們在集成私有Pod過程中,將
AFNetworking這種第三方庫用用Cocoapods管理,其實(shí)是打成了.a,而金融sdk仍然使用framework,打成.framework,因此二者無法鏈接,在Link階段報錯。解決方案是,要么將金融打成.a,要么在金融打成sdk時不勾選AFNetworking。
gitmodule的關(guān)系與解決方案
子模塊和Cocoapods都是試圖解決同樣的問題。使用子模塊的業(yè)務(wù)準(zhǔn)備遷移到Cocoapods 首先需要解耦,模塊間解耦。
安裝和使用Cocoapods
CocoaPods安裝步驟
- 升級Ruby環(huán)境,更新gem 源**
終端輸入:$sudo gem update --systemps:國內(nèi)需要切換源
- 安裝CocoaPods要訪問cocoapods.org,該網(wǎng)站已經(jīng)被天朝墻壁,需要更換鏡像來安裝(淘寶鏡像已經(jīng)停止更新)
1、gem sources --removehttps://rubygems.org/2、gem sources -a https://gems.ruby-china.org/3、gem sources -l
- 安裝Cocoapods
sudo gem install cocoapods
- 啟動Pod
$pod setup
Pod 常用命令
Pod創(chuàng)建Podfile文件有一下幾個步驟:
- pod 常用命令
搜索類庫 pod search AFNetworking 更新第三方庫: pod update導(dǎo)入第三方庫: pod install 可以刪除podfile中某個庫的代碼,然后: pod install 刪除第三方庫 :pod uninstall 查看Cocoapods版本: pod --version 查找第三方庫: pod search AFNetworking
- $ cd 到工程文件目錄,然后創(chuàng)建Podfile文件
$ touch Podfile(創(chuàng)建Podfile文件)
- $ vim Podfile編輯該文件,然后通過wq保存(具體可參考vim命令行)
platform :ios, '7.0' inhibit_all_warnings! pod 'SDWebImage', '3.7.3' pod 'SSZipArchive', '1.0.1' pod 'JSPatch', '0.1.5' pod 'TMCache', '2.1.0' pod 'FLEX', '2.2.0'配置成功后執(zhí)行命令
$ pod install
- 項(xiàng)目新增四個文件, Podfile、Podfile.lock、.xcworkspace、podfilelock.manifest以后就可以使用Pod來管理自己的組件庫,
- 以后打開后綴名為 .xcworkspace文件打開工程
pod語義化版本規(guī)范
pod 'AFNetworking' // 不顯式指定依賴庫版本,表示每次都獲取最新的版本 pod 'AFNetworking', '2.0' //只使用2.0版本 pod 'AFNetworking', '> 2.0' //使用高于2.0的版本 pod 'AFNetworking', '>= 2.0' //使用大于或等于2.0的版本 pod 'AFNetworking', '< 2.0' //使用小于2.0的版本 pod 'AFNetworking', '<= 2.0' //使用小于或等于2.0的版本 pod 'AFNetworking', '~> 0.1.2' //使用大于等于0.1.2但小于0.2的版本 pod 'AFNetworking', '~>0.1' //使用大于等于0.1但小于1.0的版本 pod 'AFNetworking', '~>0' //高于0的版本,寫這個限制和什么都不寫是一個效果,都表示使用最新版本over.
Podfile與多target
Podfile本質(zhì)上是用來描述Xcode工程中的targets用的。如果我們不顯式指定Podfile對應(yīng)的target,Cocoapods會創(chuàng)建一個名為default的隱式target,會和我們工程中的第一個target對應(yīng)。換句話說,如果在Podfile中沒有指定target,那么只有工程中的第一個target能夠使用Podfile中的描述的Pods依賴庫。根據(jù)需要,給不同的target指定Pods依賴庫。
- 例如,名稱為MyApp的target和MyPro app的target都需要Reachabilitiy、SBJson、AFNetworking三個Pods依賴庫,可以使用link_with關(guān)鍵字來實(shí)現(xiàn),將Podfile寫成如下形式:
link_with 'MyApp', 'MyApp pro' platform :ios pod 'Reachability', '~> 3.0.0' pod 'SBJson', '~> 2.6.0' platform :ios , '7.0' pod 'AFNetworking'
- 不同的target使用完全不同的Pods依賴庫
CocoaPodsTest這個target使用的是Reachability、SBJson、AFNetworking三個依賴庫,但Second這個target只需要使用OpenUDID這一個依賴庫,這時可以使用target關(guān)鍵字,Podfile的描述方式如下:
target :'MyApp' do platform :ios pod 'Reachability', '~> 3.0.0' pod 'SBJson', '~> 4.0.0' platform :ios, '7.0' pod 'AFNetworking', '~> 2.0' end target :'MyApp pro' do pod 'OpenUDID', '~> 1.0.0' end
- over
主App link Pods庫
在集成Cocoapods后,主App可以編譯通過,但是無法link到Pods 庫的情況。首先,我們看一下主App是如何引入Pods中的項(xiàng)目,編譯沒有問題,關(guān)鍵在于link。
Cocoapods與持續(xù)集成
集成Cocoapods后對項(xiàng)目的持續(xù)集成的影響。項(xiàng)目采用OClint進(jìn)行持續(xù)集成,集成Cocoapods之后,該將哪些文件加入到持續(xù)集成中。
Cocoapods與項(xiàng)目SDK化
MyApp項(xiàng)目中集成了Cocoapods,使用Cocoapods管理第三方庫公共庫,類似AFNetworking、MJExtension等,同時使用私有Pod管理MyFoundation等私有組件。并且建立私有Pod管理單品類業(yè)務(wù)。因此主App中Pods分為三部分:
- 開源第三方庫
- MyApp私有組件庫(Foundation、Catogery等)
- 單品類業(yè)務(wù)(MyApp主要涉及酒店模塊、機(jī)票模塊等)
對于這幾部分,Cocoapods會將Pods打成libPods.a,獨(dú)立模塊供主App使用。
遇到的一個問題是,因?yàn)轫?xiàng)目中存在金融模塊的SDK(部分模塊已經(jīng)SDK化),而金融業(yè)務(wù)代碼用到了AFNetworking,金融業(yè)務(wù)代碼使用AFNetworking的方式是,主App給金融SDK一個AFNetworking的framework,金融使用該framework后可以調(diào)試相關(guān)代碼,但是在金融打成framework給主App時不勾選AFNetworking這個target。因此具體的是:
金融SDK -->link --> 主App AFNetworking(AFN手動導(dǎo)入主App).到目前為止,沒有導(dǎo)致任務(wù)問題。
然后如果集成Cocoapods后,AFNetworking放在Pods中管理,而Pods被Cocoapods打成了podlib.a,.a與.framework的訪問就會出問題, .framework無法link到.a里的AFNetworking,最終導(dǎo)致link錯誤。對于這個問題,估計有多種可行的方案:
- 方案一:給金融模塊提供 AFNetworking.a 而不是 AFNetworking.framework。
- 方案二:金融模塊打framework時剔除AFNetworking ,在其打成framework時不勾選 AFN相關(guān)文件。(這種方式通過檢驗(yàn),因?yàn)榻鹑谀K不需要 link AFNetworking.framework)。
- 方案三:暫未定
over。
Cocoapods與App打包
目前我們App提供三種打包方式,第一是Xcode打包,第二是ipa_genator.sh腳本打包,第三是測試用jenkins打包。集成Cocoapods后,這三種打包方式相關(guān)配置需要更改,否則不支持打包或者打包失敗。
- Xcode打包,只需要使用MyApp.xcworkspace來編譯運(yùn)行程序,就可以打包成功。
- 腳本打包,需要更改相關(guān)配置,更改如下:
#config.cfg文件為腳本打包路徑配置文件,之前的路徑指向的是MyApp.xcodeproj,我們需要將PROJECT_NAME改為: PROJECT_NAME="MyApp.xcworkspace" #因?yàn)槊看未虬枰紫萣uild,而項(xiàng)目集成Cocoapods后,build路徑是xcworkspace而不是原來的xcodeproj,因此需要指定正確的路徑。#其次,我們需要將ipa_generator.sh文件中的 PROJ_EXT=".xcodeproj" #此處改為 PROJ_EXT=".xcworkspace" xctool_archive() { xctool -project $1 \ # 此處改為xctool -workspace -scheme $2 \ -reporter json-compilation-database:compile_commands.json \ -sdk iphoneos \ archive \ -archivePath $3 } xcodebuild_archive() { xcodebuild -project $1 \ # 此處改為xctool -workspace -scheme $2 \ -sdk iphoneos \ archive \ -archivePath $3 \ | tee xcodebuild.log }over.
- jenkins打包失敗的問題。
- ?
Cocopods集成時間表
將原來的手動添加的第三方庫遷移到現(xiàn)在的Cocoapods管理第三方庫,需要將原來第三方庫的配置相關(guān)的文件刪除干凈。Cocoapods會將第三方庫的所有需要配置的靜態(tài)庫或者文件集成在libPods.a靜態(tài)庫中,在Build Phases中可以找到這個.a靜態(tài)庫。鑒于這個考慮,我們需要刪除原來手動添加的第三方庫的配置文件。
紀(jì)錄所有的原來的第三方庫的配置文件,一并刪除
- AFNetworking
- FLEX
- FMDB
- ...
Cocoapods常見問題匯總
Pods依賴庫已經(jīng)更新
Cocoapods無法安裝的問題。
Mac系統(tǒng)升級到10.11使用Cocoapods出現(xiàn)pod:command not found 解決方案
$ sudo gem install -n /usr/local/bin cocoapods如果podupdate 或者pod install 還卡在哪兒,則
- pod install 或者pod update 速度慢的問題
查看ruby源,更換為淘寶鏡像,如果還出現(xiàn)問題,則 原因可能是:當(dāng)執(zhí)行以上兩個命令時會升級Cocoapods的Specs倉庫,加一個參數(shù)就可以省略這一步,然后速度可能會提升。參數(shù)命令如下: pod install --verbose --no-repo-update pod update --verbose --no-repo-update 執(zhí)行完命令以后有時還是會報錯,不妨更新一下本地repo pod repo update
- 這個問題是比較常見的問題
"podfile.lock" not such file or directory......http://stackoverflow.com/questions/17072396/cocoapods-errors-on-project-build
- 集成Cocoapods編譯通過但是鏈接不通過的問題。
Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_AFNetworking", referenced from: objc-class-ref in HJCXMPPTools.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)小編發(fā)現(xiàn),小編之前是手動導(dǎo)入的AFNetworking這個第三方庫,小編估計是手動導(dǎo)入時更改了某些配置文件導(dǎo)致與Cocoapods集成時的配置文件發(fā)生沖突,導(dǎo)致無法link。于是小編在此用Cocoapods更新框架時,發(fā)現(xiàn)終端的一段警告:
[!] The `myQQ [Debug]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods/Pods.debug.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target.這下的思路應(yīng)該是,手動導(dǎo)入AFN時修改了某些配置,修改了Other Linker Flags。
所以解決方案是:
按照提示,在Build setting里的Other Linker Flags增加$(inherited)。喜大普奔,這個錯誤算是解決了。
over.
需要加入gitignore的文件:
對MyApp包大小的影響、對編譯時間和編譯速度的影響
如何更新第三方庫
第三方庫與項(xiàng)目代碼中的文件重名沖突
第三方庫的sdk版本與項(xiàng)目sdk版本不符時解決方案
Cocoapods軟件版本更新
Cocoapods 目前版本為 0.39.0, 最新的1.0.0為測試版
當(dāng)兩個庫同時需要使用AFNetworking時,Cocoapods會確定一個同時能被這兩個庫使用的版本,然后將同一個安裝版本鏈接到兩個不同的庫中。
安裝pod install 第三方庫過程中,Cocoapods會使用遞歸來分析所有的需求,并且建立一個代碼相關(guān)性的圖,最后將Podfile序列化為Podfile.lock
選擇的文件夾對:
Could not automatically select an Xcode project. Specify one in your Podfile like so: xcodeproj 'path/to/Project.xcodeproj'問題出在你選擇的項(xiàng)目文件夾不對,應(yīng)該選擇Iphone文件夾集成Cocoapods
如果項(xiàng)目中有與Pod同名的文件。編譯不會通過。
對于那些不在Cocoapods公共Git倉庫中的庫,可以用任何一個Git,Mercurial或者是SVN倉庫取代,并且還可以指定具體的commit,branch或者tag。 即私有pod。
pod 'Y', :git => 'https://github.com/NSHipster/Y.git', :commit => 'b4dc0ffee'
- over.