# iOS基礎 # CocoaPods使用說明書

1、什么是CocoaPods

CocoaPods 是開發 OS X 和 iOS 應用程序的一個第三方庫的依賴管理工具。利用它可以定義自己的依賴關系 (稱作 pods),并且隨著時間的變化,以及在整個開發環境中對第三方庫的版本管理非常方便。這里整理了從基本安裝到使用的操作流程和期間容易出現的問題以及解決辦法。

2、CocoaPods都做了什么

簡單查看一下cocoapods源代碼ruby語言),了解一下install和update過程都干了什么。 參考:cocoapods都做了什么

CocoaPods/lib/cocoapods/command/install.rb

def run
    verify_podfile_exists!
    installer = installer_for_config //Podfile的內容解析
    installer.repo_update = repo_update?(:default => false)
    installer.update = false //和update的區別
    installer.install!
 end

CocoaPods/lib/cocoapods/command/update.rb

def run
    verify_podfile_exists!

    installer = installer_for_config
    installer.repo_update = repo_update?(:default => true)
    if @pods
      verify_lockfile_exists!
      verify_pods_are_installed!
      installer.update = { :pods => @pods }
    else
      UI.puts 'Update all pods'.yellow
      installer.update = true
    end
    installer.install!
end

CocoaPods/lib/cocoapods/installer.rb

def install!
  prepare
  resolve_dependencies //處理依賴關系、比如是根據本地specs文件呢還是遠端git地址等
  download_dependencies//跟進依賴關系下載對應依賴包
  validate_targets
  generate_pods_project //生成pods.xcodeproj工程,將依賴中的文件、Library加入工程,設置target dependencies、生成workspace//
  if installation_options.integrate_targets?
    integrate_user_project
  else
    UI.section 'Skipping User Project Integration'
  end
  perform_post_install_actions
end

總結

Podfile的內容解析

repo的更新檢查

處理Podfile中的依賴關系

下載依賴資源

生成pods.xcodeproj工程

將依賴中的文件、Library加入工程

設置target dependencies

生成workspace

3、CocoaPods的安裝

1.安裝過程

安裝方式異常簡單 , Mac 下都自帶 ruby,使用 ruby 的 gem 命令即可下載安裝:

$ sudo gem install cocoa pods

$ pod setup

2.安裝過程可能出現的錯誤

gem版本需要更新

首先確認軟件源地址是正確的,然后如果你的 gem 太老,可能也會有問題,可以嘗試用如下命令升級 gem。

$ sudo gem update –system  //sudo 執行 不然會報無權限錯誤

更新完成 gem 后 :

$ gem update cocoapod //更新cocoapod

$ pod setup pod //更新完成后初始化

$ pod repo update —verbose //更新repo

如果報錯,先移除原來的緩存文件:

$ rm -rf ~/.cocoapods/repos/master //然后再 pod setup。

pod setup 卡住在 Setting up CocoaPods master repo

這步其實是 Cocoapods 在將它的信息下載到 ~/.cocoapods 目錄下,如果你等太久,可以試著 cd 到那個目錄,用 du -sh * 來查看下載進度。

如果還是慢,更新一下軟件源:

ruby 的軟件源 https://rubygems.org 因為使用的是亞馬遜的云服務,所以被墻了,需要更新一下 ruby 的源。并且由于淘寶源已經不再進行更新維護,改成由 ruby-china 管理維護 所以源改成 https://gems.ruby-china.org/

gem sources –remove https://rubygems.org // 移除默認源

gem sources -a https://gems.ruby-china.org // 添加新的源

gem sources -l //查看sources源 看是否已經更換

4、CocoaPods基礎應用

1.項目中的使用方法

使用時需要新建一個名為 Podfile 的文件,以如下格式,將依賴的庫名字依次列在文件中即可:

source 'https://github.com/CocoaPods/Specs.git' //可以在這里按這種格式配置其他倉庫
target 'MyApp' do 
platform :ios, '6.0' //IOS 系統、版本要求
pod 'MJExtension', '~> 2.5.12' //引入的pod項目對應的項目名稱 和版本號
platform :ios,'7.0' 
pod 'FMDB','~> 2.6.0'//~>符號指的是 2.6 級別版本獲取最新的版本'
end

然后你將編輯好的 Podfile 文件放到你的項目根目錄中,執行如下命令即可:

cd “你的podfile所在目錄”

pod install

現在,你的所有第三方庫都已經下載完成并且設置好了編譯參數和依賴,你只需要記住如下:

使用 CocoaPods 生成的 .xcworkspace 文件來打開工程,而不是以前的 .xcodeproj 文件。

每次更改了 Podfile 文件,你需要重新執行一次 pod update 命令。

當不知道某款第三方庫的引入方法時可以直接在終端查找第三方庫 或者 你如果不知道 CocoaPods 管理的庫中,是否有你想要的庫,那么你可以通過 pod search xxx 命令進行查找

2.CocoaPods使用中的tips

1.關于 Podfile.lock

當你執行 pod install 之后,除了 Podfile 外,CocoaPods 還會生成一個名為 Podfile.lock 的文件,Podfile.lock 應該加入到版本控制里面,不應該把這個文件加入到 .gitignore 中。

因為 Podfile.lock 會鎖定當前各依賴庫的版本,之后如果多次執行 pod install 不會更改版本,要pod update 才會改 Podfile.lock 了。

這樣多人協作的時候,可以防止第三方庫升級時造成大家各自的第三方庫版本不一致。

后面的CocoaPods私人倉庫創建會講到 podspec 文件的問題

2.–-no-repo-update

CocoaPods 在執行 pod install 和 pod update 時,會默認先更新一次 podspec 索引,會去更新 repo。

使用 --no-repo-update 參數可以禁止其做索引更新操作。如下所示:

pod install –-no-repo-update

pod update –-no-repo-update

3.移除tag0.0.1,再重現提交新的tag0.0.1

git add . 
git commit -m"cover tag 0.0.1" 
git push 
git tag -d 0.0.1 
git push origin :refs/tags/0.0.1 
git tag 0.0.1 
git push origin 0.0.1

4.CocoaPods原理

大概研究了一下 CocoaPods 的原理,它是將所有的依賴庫都放到另一個名為 Pods 項目中,然后讓主項目依賴 Pods 項目,這樣,源碼管理工作都從主項目移到了 Pods 項目中。發現的一些技術細節有:

1.Pods 項目最終會編譯成一個名為 libPods.a 的文件,主項目只需要依賴這個 .a 文件即可。

2.對于資源文件,CocoaPods 提供了一個名為 Pods-resources.sh 的 bash 腳本,該腳本在每次項目編譯的時候都會執行,將第三方庫的各種資源文件復制到目標目錄中。

3.CocoaPods 通過一個名為 Pods.xcconfig 的文件來在編譯時設置所有的依賴和參數。

3.創建私有倉庫

使用pod的時候 我們會遇到需要將自己的代碼封裝出去 單獨管理的情況,這種情況下 我們就需要一個私有的倉庫來管理這些單獨的部件。

1.創建一個支持pod引入的項目

cocoapods提供了一個快捷的項目模板創建命令:

$ pod lib create 你要創建的項目的項目名稱

執行命令會有如下選擇過程:

//pod lib create 你要創建的項目的項目名稱  命令執行后會詢問基本信息
//1.是否需要一個例子工程;2.選擇一個測試框架;3.是否基于View測試;4.類的前綴;

What language do you want to use?? [ Swift / ObjC ]
 > ObjC

Would you like to include a demo application with your library? [ Yes / No ]
 > yes

Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > none

Would you like to do view based testing? [ Yes / No ]
 > no

What is your class prefix?
 > YG

依次按需要執行完成就會生成一個有格式的項目。

生成項目分為 Example 和 Pods 兩個主要的目錄。

Pods 
|- Assets 文件夾,//用來存放本地資源,比如圖片、Assets.xcassets等
|- Classes 文件夾,//存放pod的.m.h.swift.xib文件等
| 
Example 文件夾,//就是一個demo項目方便pod代碼開發
|   |- demoProject.xcodeproj
|   |- demoProject.xcworkspace
|   |- Podfile   //就是一個demoPod項目的 第三方庫依賴描述文件
|   |- Podfile.lock
|   |- demoProject
|   |- Pods      //其他第三方庫依賴描述文件存放文件夾
|   |- Tests
LICENSE //開源協議文件
| 
demoProject.podspec  //這個pod文件的說明書,下面會詳細說

項目在xcode中的結構如下:

png

其中重要的兩個部分是 *.podspec 文件 和 pods下面的 Development Pods 目錄其實就是上面提到的Pod目錄。.podspec 就像一個說明書,描述當前這份pod項目 需要提交到私有庫中,才能讓其他項目通過私有庫引用到當前這份pod項目。

*.podspec 內容格式基本如下:

Pod::Spec.new do |s| 
s.name = “demoProject” //項目名 
s.version = “1.0.2” //版本號 要和在git上的tag對應 
s.summary = “demo” 
s.description = <<-DESC 
this is a demo 
DESC 
s.homepage = “git@gitlab.jfz.net:xxxx/demoProject” //項目主頁 
s.license = ‘MIT’ 
s.author = { “young” => “young.huang@jfz.com” } //用戶信息 
s.source = { :git => “git@gitlab.jfz.net:xxx/demoProject.git”, :tag => s.version.to_s }//git地址 
s.platform = :ios, ‘6.0’ //支持系統、最低版本 
s.requires_arc = true  //是否使用ARC,如果指定具體文件,則具體的問題使用ARC
s.source_files = ‘Pod/Classes/*/.{h,m}’ //項目核心部分的文件 class下面的所有.h/.m文件

#s.source_files = 'Pod/Classes/**/*'//代碼源文件地址,**/* 表示Classes目錄及其子目錄下所有文件,如果有多個目錄下則用逗號分開,如果需要在項目中分組顯示,這里也要做相應的設置

# s.public_header_files = ‘Pod/Classes/*/.h’ //公開頭文件地址
# s.frameworks = ‘UIKit’, ‘MapKit’ //此pod項目使用到得框架 
# s.dependency ‘AFNetworking’, ‘~> 2.3’ //此pod項目依賴的其他pod項目

end

subspec語法參考

修改pod項目并提交到指定地址 給項目打上tag 這里的tag需要和podspec中配置的tag一樣。

$ git tag 1.0.0

$ git push origin v1.0.0

特別注意 :

1.每次往Pod里面添加文件、圖片、等任何非代碼級別的改動的時候,都需要在Example目錄下面進行一次pod install 或者 pod update一次。

2.版本管理忽略掉pods文件夾 保留 podfile podfile.lock 跟著版本同步

2.創建私有倉庫

首先創建放私有庫(repo) git地址 :

git@gitlab.xxx.net:xxxxx/demoRepo.git

然后在添加一個叫 demoRepo 的本地repo,并指向之前創建好的git地址,控制臺命令:

$ pod repo add demoRepo git@gitlab.xxx.net:xxxxx/demoRepo.git
$ pod repo //查看本地所有repo

私有庫創建好了后,回到之前創建的pod項目下,一般修改好podspec后會進行校驗必須是無錯誤、無警告才能提交。校驗命令:

pod lib lint //只是本地格式校驗

pod spec lint YoungEwm.podspec //這個命令除開校驗格式  還需要校驗遠程地址,鏈接的項目地址等

將修改好的podspec文件push到我們剛剛創建的demoRepo上。加上 –-verbose命令會打印操作日志

$ pod repo push demoRepo demoProject.podspec –-verbose

到最后如果是因為警告原因(warn)無法通過則在push命令后如上 --allow-warnings 即可。成功提交后在我們的demoRepo對應的git remote端就可以看到一個對應版本的 pod spec 文件。

├─ LICENSE
├─ demoProject
│   └─ 1.0.2
│       └─ demoProject.podspec
└─ README.md

3.獲取私有倉庫中的pod項目

上面已經將我們自己創建的項目注冊到了我們自己的私有repo中,在我們的主項目中需要引入這些pod部件的時候。首先在項目的 .xcodeproj 文件同級 創建一個 podfile 文件 文件內容如下:

source ‘https://github.com/CocoaPods/Specs.git’ 引用的源 cocoapods的公用源 
source ‘git@gitlab.jfz.net:huangyang/demoRepo.git’ 我們自己的私有源

platform :ios, ‘6.0’ 
target ‘demoWebView’ do 
pod ‘JFZPodsDemo’, ‘~> 1.0.1’ //我們需要引入的pod項目 ~> 表示是 1.0.X 版本級別的更新 前兩位不改變

end

這里面的 platform 版本要和 podspec 里面設置的不能沖突,否則無法引用pod項目

然后重新 pod install 一下就好了

4.刪除repo

如何刪除一個私有Spec Repo,只需要執行一條命令即可:

pod repo remove demoRepo

這樣這個Spec Repo就在本地刪除了,我們還可以通過

pod repo add demoRepo git@coding.net:wtlucky/WTSpecs.git

再把它給加回來。

如果我們要刪除私有Spec Repo下的某一個podspec怎么操作呢,此時無需借助Cocoapods,只需要cd到~/.cocoapods/repos/demoRepo 目錄下,刪掉庫目錄。

~/.cocoapods/repos/demoRepo$ rm -Rf demoRepoXXX

然后在將Git的變動push到遠端倉庫即可。

5.可能遇見的問題

spec文件無法校驗通過

發生原因:

當spec本身格式有錯誤的時候

當引用多個私有repo中得pod項目,直接指向cocoapods查詢不到對應的pod所屬的私有repo

解決辦法 :

在pod repo push 后跟上對repo的地址指向 -- source=。已經添加到本地的repo 可以直接用repo名稱,沒有的使用git地址。

--sources=https://github.com/artsy/Specs,master  

6.開發pod項目的其他問題

1.怎么在開發中調試程序

開發過程中,可以修改Podfile文件的,將pod版本指向本地。對應pod的代碼會被引入Development Pods中:

#pod 'Stock', :path => '/Users/xxxx/desktop/workplace/Stock'

2.模塊之間的命名問題

最好以模塊為單位添加不同的前綴。

3.Pod之間的引用

4.tag緩存問題

添加pod的某個tag如0.0.1 到repo后,需要修改代碼但又不想提升tag版本時,注意修改完后清理CocoaPods的本地緩存

$ rm -rf “${HOME}/Library/Caches/CocoaPods”

5.第三方庫的修改,盡量fork再通過pod引用

6.ignore 文件忽略問題

有時候突然想要忽略某個文件,但是跟新 .gitignore 以后,remote 端并沒有馬上刪除這個文件,原因是ignore文件只能忽略沒有加入版本管理的文件,已經被納入了版本管理的文件是無效的

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

7.使用ssh協議(見git使用中得ssh描述)

8.解決ArgumentError - invalid byte sequence in US-ASCII錯誤
修改終端語言、地區等國際化環境變量

export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8

9.CI-SSH 問題

#解決ci遠程slave訪問git時,要求驗證私鑰密碼問題
#即,pod install 時,跟新pod的訪問權限問題
#$SSH_PARIVATE_KEY_PASS變量為私鑰密碼
#為了安全在jenkins的環境變量里面設置這個常量
eval $(ssh-agent)
expect << EOF
spawn ssh-add $1
expect "Enter passphrase"
send "$SSH_PRIVATE_KEY_PASS\r"
expect eof
EOF

10.其他知識點

pod 在多人協作的時候 如何保證 發布版本不會跟著開發走動 :

我們從開發過程可以看到 當我們pod install的時候 會出現下面代碼:

Pre-downloading: `Category` from `git@gitlab.xxx.net:xxx_iOS/Category.git`, commit `e244ac83e027b8f6247e702603ecf0209c9d4878`

這里說明 Category這個庫 更新了 pod去拉取Category庫最新的代碼

cocoapods是根據 podfile文件中得 配置去指向指定庫 同時 也有一個pod.lock文件 這個文件用于鎖定 pod拉取代碼的 commit 節點。如下是Category在pod.lock文件中生成的,commit 就是指向對應commit節點。

Category:
:commit: 03c7a540b5c24eda6cea048048adef887cbbc77a
:git: git@gitlab.jfz.net:gxq_iOS/JFZReportModule.git

當然 如果是已經打了tag的不存在這個問題 因為它是按tag去拉取,這里針對的時尚未打tag的庫。

5、CocoaPods高級應用

podfile文件的更多應用

1、pod引用參數

1、Build configurations(編譯配置)

pod 'PonyDebugger', :configurations => ['Debug', 'Beta']

2、Subspecs(子模塊)

pod 'QueryKit', :subspecs => ['Attribute', 'QuerySet']
pod 'QueryKit/Attribute'

3、branch、tag、commit

pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :branch => 'dev'
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :tag => '0.7.0'
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :commit => '082f8319af'

4、指定podspec

pod 'JSONKit', :podspec => 'https://example.com/JSONKit.podspec'

2、target

一個工程多個taget需要不同pod配置項的時候

workspace 'xxx.xcworkspace' 指定對應xcworkspace
target :ZipApp do
  project 'FastGPS' 指定對應project

  pod 'SSZipArchive'
end

使用自定義構建配置
project 'TestProject', 'Mac App Store' => :release, 'Test' => :debug

3、inhibit_all_warnings!

屏蔽cocoapods庫里面的所有警告

inhibit_all_warnings!
or
pod 'SSZipArchive', :inhibit_warnings => true

4、pre_install

這個鉤子允許你在Pods被下載后但是還未安裝前對Pods做一些改變

pre_install do |installer|
  # Do something fancy!
end

5、post_install

這個鉤子允許你在生成的Xcode project寫入硬盤或者其他你想執行的操作前做最后的改動

給所有target自定義編譯配置

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['GCC_ENABLE_OBJC_GC'] = 'supported' //配置環境變量等
    end
  end
end

6、abstract_target

抽象target、當多個target的工程并且工程中各個target之間有很大一部分依賴是相同的時候,我們可以抽象出一個抽象target

抽象target中的所有target都自動繼承抽象target定義的所有依賴

abstract_target 'Shows' do
  pod 'ShowsKit'

  # The target ShowsiOS has its own copy of ShowsKit (inherited) + ShowWebAuth (added here)
  target 'ShowsiOS' do
    pod 'ShowWebAuth'
  end

  # The target ShowsTV has its own copy of ShowsKit (inherited) + ShowTVAuth (added here)
  target 'ShowsTV' do
    pod 'ShowTVAuth'
  end

  # Our tests target has its own copy of
  # our testing frameworks, and has access
  # to ShowsKit as well because it is
  # a child of the abstract target 'Shows'

  target 'ShowsTests' do
    inherit! :search_paths
    pod 'Specta'
    pod 'Expecta'
  end
end

7、其他參數 swift_version、platform、use_frameworks、inherit

swift_version:指定swift版本號
swift_version = '4.0'

platform:指定系統、版本 

platform :ios, '4.0'
platform :ios

use_frameworks:使用動態庫
use_frameworks!

inherit! :search_paths
明確指定繼承于父層的所有pod,默認就是繼承的

6、參考文獻

cocoapods官網

cocoapods都做了什么

cocoapods——dqk

https://kemchenj.github.io/2019-05-31/#more

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,860評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,025評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,421評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,642評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,177評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,970評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,157評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,410評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,896評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,157評論 2 375

推薦閱讀更多精彩內容