# iOS基礎 # CocoaPods使用說明書

1、什么是CocoaPods

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

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的區(qū)別
    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 //處理依賴關系、比如是根據(jù)本地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.安裝過程可能出現(xiàn)的錯誤

gem版本需要更新

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

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

更新完成 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 的源。并且由于淘寶源已經(jīng)不再進行更新維護,改成由 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源 看是否已經(jīng)更換

4、CocoaPods基礎應用

1.項目中的使用方法

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

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

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

cd “你的podfile所在目錄”

pod install

現(xiàn)在,你的所有第三方庫都已經(jīng)下載完成并且設置好了編譯參數(shù)和依賴,你只需要記住如下:

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

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

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

2.CocoaPods使用中的tips

1.關于 Podfile.lock

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

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

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

后面的CocoaPods私人倉庫創(chuàng)建會講到 podspec 文件的問題

2.–-no-repo-update

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

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

pod install –-no-repo-update

pod update –-no-repo-update

3.移除tag0.0.1,再重現(xiàn)提交新的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 項目中。發(fā)現(xiàn)的一些技術細節(jié)有:

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

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

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

3.創(chuàng)建私有倉庫

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

1.創(chuàng)建一個支持pod引入的項目

cocoapods提供了一個快捷的項目模板創(chuàng)建命令:

$ pod lib create 你要創(chuàng)建的項目的項目名稱

執(zhí)行命令會有如下選擇過程:

//pod lib create 你要創(chuàng)建的項目的項目名稱  命令執(zhí)行后會詢問基本信息
//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

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

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

Pods 
|- Assets 文件夾,//用來存放本地資源,比如圖片、Assets.xcassets等
|- Classes 文件夾,//存放pod的.m.h.swift.xib文件等
| 
Example 文件夾,//就是一個demo項目方便pod代碼開發(fā)
|   |- demoProject.xcodeproj
|   |- demoProject.xcworkspace
|   |- Podfile   //就是一個demoPod項目的 第三方庫依賴描述文件
|   |- Podfile.lock
|   |- demoProject
|   |- Pods      //其他第三方庫依賴描述文件存放文件夾
|   |- Tests
LICENSE //開源協(xié)議文件
| 
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’ //支持系統(tǒng)、最低版本 
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.創(chuàng)建私有倉庫

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

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

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

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

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

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

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

將修改好的podspec文件push到我們剛剛創(chuàng)建的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項目

上面已經(jīng)將我們自己創(chuàng)建的項目注冊到了我們自己的私有repo中,在我們的主項目中需要引入這些pod部件的時候。首先在項目的 .xcodeproj 文件同級 創(chuàng)建一個 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,只需要執(zhí)行一條命令即可:

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文件無法校驗通過

發(fā)生原因:

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

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

解決辦法 :

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

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

6.開發(fā)pod項目的其他問題

1.怎么在開發(fā)中調試程序

開發(fā)過程中,可以修改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文件只能忽略沒有加入版本管理的文件,已經(jīng)被納入了版本管理的文件是無效的

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

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

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

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的環(huán)境變量里面設置這個常量
eval $(ssh-agent)
expect << EOF
spawn ssh-add $1
expect "Enter passphrase"
send "$SSH_PRIVATE_KEY_PASS\r"
expect eof
EOF

10.其他知識點

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

我們從開發(fā)過程可以看到 當我們pod install的時候 會出現(xiàn)下面代碼:

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

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

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

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

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

5、CocoaPods高級應用

podfile文件的更多應用

1、pod引用參數(shù)

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寫入硬盤或者其他你想執(zhí)行的操作前做最后的改動

給所有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' //配置環(huán)境變量等
    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、其他參數(shù) swift_version、platform、use_frameworks、inherit

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

platform:指定系統(tǒng)、版本 

platform :ios, '4.0'
platform :ios

use_frameworks:使用動態(tài)庫
use_frameworks!

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

6、參考文獻

cocoapods官網(wǎng)

cocoapods都做了什么

cocoapods——dqk

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容