問題描述
環信的EaseUI的pod文件依賴于MWPhotoBrowser,而MWPhotoBrowser又依賴于MBProgressHUD ,'~>0.9',問題就出在這個0.9上面了,根據CocoaPods官方文檔對于Podspec Syntax的語法描述。
其版本號規則為匹配指定的最后一位數字以上,但不能超過前一位,而實際上MBProgressHUD的版本號已經更新到1.0.0了,也就是說MWPhotoBrowser指定的版本號規則無法使用1.0.0版本。
而項目里之前已經通過pod依賴了MWPhotoBrowser的1.0.0版本,并且1.0.0的api又較大改動,當降級到0.9.2時,編譯錯誤多達上百處。
而且MWPhotoBrowser的項目已經一年多不再維護,其依賴的MBProgressHUD、SDWebImage都存在版本過低的現象,github的issue里也是怨聲載道。
如此看來等作者解決這個問題是不可能了,只能靠自己work round了。
解決辦法
1、在MWPhotoBrowser的issue里找到一個家伙的留言,說他fork并更新了MWPhotoBrowser依賴庫版本問題,就用它吧。https://github.com/EvoIos/MWPhotoBrowser
2、由于EaseUI里依賴的spec.dependency MWPhotoBrowser 沒法直接修改,并且也不支持通過:git =>指定下載來源的語法。這里有兩個解決方案:一是先fork該項目,然后修改fork后的podspec里的spec.dependency,去掉MWPhotoBrowser,然后在自己的項目的Podfile里通過pod 'MWPhotoBrowser', git => 的方式引入上一步修改過的類庫。但這里存在的問題是,EaseUI更新比較頻繁,fork以后為了與官方庫同步要經常主動去pull request才可以,比較麻煩。
3、第二個解決方案就是,不fork EaseUI,也不去掉MWPhotoBrowser,繼續使用環信官方的EaseUI pod。然后直接像上一步一樣在自己的項目的Podfile里通過pod 'MWPhotoBrowser', git => ,本來我以為podspec中指定的spec.dependency一定會去官方庫或者source命令指定的私有庫里去查詢,但實際上通過pod update --verbose命令的執行情況來看,pod的執行邏輯是預先通過Pre-downloading操作加載所有用戶指定的來自私有庫的類庫(先查緩存目錄,沒有的話則從私有庫指定的網絡地址下載到緩存中),然后再檢查每個庫的依賴情況,如果依賴的庫已經在私有庫中指定并且預加載處理過,則不到Cocoapods的官方spec或者source指定的私有spec中去查詢和匹配,而是直接使用已經加載處理過的。
4、fork后的pod項目,不需要修改podspec中的source,因為只有從Cocoapods的spec中搜索到的庫才需要從podspec中讀取source來獲取源文件。如果是在Podfile中直接指定:git =>的私有庫的地址,而不是通過查詢spec倉庫里的podspec方式匹配來加載的情況下,即使git私有庫的項目里podspec指定了spec.source路徑,pod執行的時候也會忽略該source路徑設置,而是一定會把:git=>指向的地址作為source路徑,所以podspec中指定的source在這里不起作用,不過其他的像source_files等配置和編譯屬性還是起作用的。
5、通過pod加載本地的類庫時,也就是pod '類庫名', :path => '本地路徑' 這種方式加載本地的類庫時,在路徑下需要同時包含源文件路徑和podspec文件,pod引擎執行的時候一定會從該目錄下找源文件,而不會從podspec配置文件中指定的source地址去下載。也就是說這種方式下,podspec中的source配置也是失效的。綜上4、5兩條來說,podspec中的source配置選項,只有在通過Podfile的source命令配置的spec倉庫中找到podspec的時候才會起作用,:git和:path的方式都會忽略source,所以fork后的項目,是不需要調整來源中的podspec.source路徑的,反正pod引擎也忽略他。
6、還有一點需要注意的是,私有庫使用:git =>的方式引入,必須要配合:tag或者:commit命令指定其來源的commit id,如果不指定的話,pod引擎會忽略掉podspec中指定的tag(很明顯tag是source的一個子屬性,source都忽略了肯定也忽略tag),而是每次都去獲得最新的一次commit的源碼。并且pod引擎不會先去查詢類庫的git中的最新commit對應的源碼是否已經在本地被緩存過,而是一定去下載最新的類庫源碼然后覆蓋緩存,這樣造成的后果就是,每次修改了Podfile文件后執行pod update的時候,都會把所有私有庫的類庫重新git clone一遍完整的源碼,非常浪費時間。但是如果指定了:tag或者:commit的話,pod引擎就會優先去緩存中查詢,成功匹配到的話就不會再去嘗試下載了。
附:一個不錯的git使用中文教程 http://gitbook.liuhui998.com/index.html
更新2017-05-22
嘗試了一種新的引入pod依賴的方式,即自定義specs倉庫。
1、在github上建立一個新的git倉庫ZXSpecs。
2、進入本地~/.cocoapods/repos目錄,通過git clone下載上一步創建的ZXSpecs。
3、當前下載下來的空的,但是有.git配置文件,然后在ZXSpecs目錄下新建自己定義的podspec文件。注意必須是ZXSpecs/Specs/類庫名/版本號/.podspec文件,這種目錄結構,不符合這種目錄的話使用pod repo lint命令驗證的時候會報錯誤。
4、創建完成podspec文件后,通過pod repo push ZXSpecs xxx.podspec的方式加入到遠程倉庫中。但這種方式我一直沒成功,總是報錯(后來證明這種方法需要本地有podspec對應的源碼結構,以及源碼對應的github遠程倉庫才能好用),所以就換成直接操作git進行commit然后push的方式。
5、使用上一步的git push的方式添加spec也要保證符合第三步目錄結構,試了一下如果不加<類庫名>這一級目錄,則pod查找的時候則匹配不到,同名的話會找下一個source中指定的。如果加了<類庫名>但是沒有加<版本號>,則執行pod update的時候報錯不能轉換nil。
6、通過這種方式加入的自己fork后修改過的spec,由于pod的機制是從前往后找source里指定的specs倉庫里第一個匹配的,所以要把自己定義的倉庫寫在github/cocoapods官方庫的前面。另外同名的庫會報警告。
[!] Found multiple specifications for `MWPhotoBrowser (2.1.2)`:
- /xxx/.cocoapods/repos/ZXSpecs/Specs/MWPhotoBrowser/2.1.2/MWPhotoBrowser.podspec
- /xxx/.cocoapods/repos/AliyunSpecs/Specs/d/7/3/MWPhotoBrowser/2.1.2/MWPhotoBrowser.podspec.json
不用管它,反正是引用的第一個沒問題。再就是發現如果podspec是用.json的方式提供的話,就不會報這個重復定義警告。
7、原始的cocoapods的repos里面的spec最好不要重命名,就保留原來的master的名字,因為很多像pod search一類的命令,都會默認去master這個名字下的specs里面去找,如果不存在的話,他會強制從github/cocoapods clone specs并且起名叫master。如果把自己從別的源(oschina,aliyun等等)clone出來的鏡像改個名字叫master,pod就會從這些進行操作了。
總結:這種寫法,相比之前的,優勢是不需要在Podfile文件里指定:git和:commit,只需要pod '類庫名'就可以了,再就是最前面需要source ‘‘自定義spec.git’’指定私有庫索引來源。如果不指定:tag或者:commit,那么每次都會使用最新的提交的代碼,并且能夠緩存,不會像使用:git私有庫那樣每次都去clone一遍。另外需要注意的就是這種方式會讀取s.source字段來下載源碼,所以fork的項目里的podspec中的source要指向fork之后的地址。
缺點是不添加新的版本號目錄的話,pod就認為該類庫沒有更新過。即使有新的提交也會忽略。
附:這篇文章寫的也不錯,更全面一點。http://blog.csdn.net/xc120313778/article/details/39956979
更新Ruby環境版本
參考資料http://www.lxweimin.com/p/80944c75c763
安裝ruby命令ruby install 2.4,過程中檢查沒有安裝過Homebrew的話會自動安裝。
順序為:Xcode -> Homebrew(可選) -> RVM -> Ruby -> CocoaPods
注意:通過rvm安裝的ruby和gem定義在~/.rvm/rubies/ruby-2.4.1/bin/目錄下,gems倉庫在.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems下。
而mac系統自帶的gem是在ruby類庫中:/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/gem。
對應的gems倉庫是在/Library/Ruby/Gems/2.0.0/gems目錄下,我之前安裝過好幾個版本的cocoapods,用find / -name pod查找一下,結果如下
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.37.1/bin/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.39.0/bin/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-1.0.1/bin/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-1.2.1/bin/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-plugins-0.4.2/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-plugins-1.0.0/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-trunk-0.6.0/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-trunk-0.6.4/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-trunk-1.0.0/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-trunk-1.2.0/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-try-0.4.4/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-try-0.5.1/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-try-1.0.0/lib/pod
/Library/Ruby/Gems/2.0.0/gems/cocoapods-try-1.1.0/lib/pod
但是通過rvm安裝了新版本的ruby以后,其實是安裝在一個新的路徑~/.rvm/rubies/ruby-2.4.1下面。并沒有替換到mac系統自帶的ruby和gem,并且rvm通過修改.bashrc和.bash_profile把自己下載的ruby路徑添加到PATH中優先級更高的位置。于是再次執行pod相關命令時候,系統會執行新安裝的gem,并且從.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems中查找pod命令(至于為什么不從原來的路徑下查找pod我也不知道,也許是通過rvm安裝ruby和gem后的腳本從PATH中刪除掉了原來/Library下的pod,因為which pod找不到),而這時會發現找不到pod命令,解決方法就是使用新的gem命令再安裝一遍cocoaPods。
新版本的gem install cocoapods的時候,會依賴于內部的xcodeproj.gem,不需要本機的xcodeproj.bin,所以也就不需要指定-n /usr/local/bin來避開蘋果10.11以后的rootless限制了。
sudo gem install cocoapods 安裝完成后的cocoapods位于:
~/.rvm/rubies/ruby-2.4.1/bin/pod
~/.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems/cocoapods-1.2.1/bin/pod
~/.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems/cocoapods-plugins-1.0.0/lib/pod
~/.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems/cocoapods-trunk-1.2.0/lib/pod
~/.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems/cocoapods-try-1.1.0/lib/pod
這樣which ruby / gem / pod,都是在.rvm/rubies/ruby-2.4.1/bin目錄下面了,對應的都是最新版本,也就是說每次更新ruby環境的版本,會同時安裝對應版本的gem到相同目錄,并且export source到PATH中,同時刪除之前的PATH,想使用pod就需要重新安裝一遍cocoapods到rvm管理的當前版本的ruby對應的目錄下。
其他相關資料
http://www.lxweimin.com/p/fb202af858fd
http://www.lxweimin.com/p/4b63dfbd8be7
http://www.lxweimin.com/p/c6c227c0c221
http://www.lxweimin.com/p/1e5927eeb341
安裝cocoapods http://www.lxweimin.com/p/b64b4fd08d3c
Homebrew的單獨安裝和使用 http://blog.csdn.net/aaawqqq/article/details/44088141? https://brew.sh
創建Cocoapods自定義類庫 http://blog.wtlucky.com/blog/2015/02/26/create-private-podspec
http://blog.csdn.net/zaitianaoxiang/article/details/39555153
Cocoapods使用自定義類庫的幾種方式 http://blog.csdn.net/xc120313778/article/details/39956979