做者:bool周 原文連接:我所理解的 CocoaPodshtml
好久以前讀了一遍 Cocoa Pods 官方文檔,對 Cocoa Pods 有了一個簡單的瞭解。時隔多日,全忘了。ios
因此再回顧一下,順便寫一篇總結。文章分爲原理和使用兩部分,比較長,能夠根據本身的需求選擇性閱讀。git
CocoaPods 是開發 OS X 和 iOS 應用程序的一個第三方庫的依賴管理工具,使用這個工具能夠簡化對組件依、更新的過程。新添加一些第三方組件能夠直接修改 podfile 而後進行 pod install
;更新已有第三方組件,能夠修改 podfile 而後進行 pod update
;本身開發的組件也能夠上傳到 CocoaPods 或者私有倉庫,供其餘人使用。github
CocoaPods 是用 ruby 寫的,由若干個 gems 組成。也就是說,iOS project 使用 CocoaPods 來進行組件管理,CocoaPods 自己也是一個 project,它使用 gem 進行組件管理。swift
開始寫這篇文章的時候,我想先寫使用,再寫原理。由於我擔憂不少人感受原理晦澀難懂,就放棄看後面了。但構思的時候發現,明白了原理以後,對一些命令的使用會有更深入的瞭解。因此仍是決定將原理放在前面講。api
CocoaPods 是用 Ruby 寫的,並由若干個 Ruby 包 (gems) 構成的,源碼託管在 GitHub 上。其中主要的幾個組件爲:xcode
CocoaPods/Specs
這個是一個保存第三方組件 podspec 文件的倉庫。第三方組件開發完成以後,會傳一份 podspec 文件傳到 CocoaPods,這個 Specs 包含了每一個第三方組件全部版本的 podspec 文件。當使用某個第三方組件時,若是這些組件支持 CocoaPods,會在 Podfile 中指定 source,例以下面這樣:ruby
source 'https://github.com/CocoaPods/Specs.git'
複製代碼 |
當執行 pod install
或 pod update
等一些命令時,便會從這個倉庫找到組件指定版本的 podspec 文件,而後根據這個 podspec 配置信息去獲取組件。bash
CocoaPods/CocoaPods
這是是一個面向用戶的組件,每當執行一個 pod 命令時,這個組件都將被激活。該組件包括了全部使用 CocoaPods 涉及到的功能,而且還能經過調用全部其它的 gems 來執行任務。app
CocoaPods/Core
這個 gem 組件提供支持與 CocoaPods 相關文件的處理,例如 Specification、Podfile 和 Source。當執行 pod install
等一些命令時。Core 組件會解析第三方組件開發者上傳的 podspec 文件和使用者的 podfile,以此肯定須要爲 project 引入哪些文件。除此以外,當執行與這些文件一些相關的命令時,也由這部分組件處理,例如使用 pod spec lint
來檢測 podspec 文件的有效性。
CocoaPods/Xcodeproj
使用這個 gem 組件,你能夠用 ruby 來建立並修改 Xcode projects。在 CocoaPods 中它負責全部工程文件的整合。若是你想要寫一個腳原本方便的修改工程文件,那麼能夠單獨下載這個 gem 並使用。更多信息能夠查看工程的 readme。
Specification
這個文件用來描述第三方組件某個版本的信息。主要包含了組件拉取地址、應該拉取那些文件和項目配置信息。除此以外,還包含一些組件信息,例如組件的名字、版本等。後面章節會詳細講解字段含義和文件書寫規範。
Podfile
這個文件用來指定工程中依賴了那些組件。主要包含了依賴的組件名、組件版本、組件地址等。後面章節會詳細講解字段含義和文件書寫規範。
Podfile.lock
在第一次執行 pod install
時,執行完畢後會生成一個 podfile.lock 文件。這個文件主要標註了項目當前依賴的具體版本。看下面這個文件信息:
有個問題須要牢記:CocoaPods 強烈建議將 Podfile.lock 文件加入版本管理,這樣其餘人同步了你的 podfile.lock 文件以後,執行 pod install
時會將按照裏面指定給的版本加載,避免多人協做時發生衝突。後面的 pod install vs pod update 會詳細講解 podfile.lock 變動時機。
Manifest.lock 是由 Podfile.lock 生成的一個副本,每次生成或者更新 Podfile.lock,都會更下 Pods 文件夾下面的 Manifest.lock 文件。若是你碰見過這樣的錯誤 沙盒文件與 Podfile.lock 文件不一樣步 (The sandbox is not in sync with the Podfile.lock),這是由於 Manifest.lock 文件和 Podfile.lock 文件不一致所引發。
上圖爲組件開發者、CocoaPods、組件使用者三者的關係。
組件開發者開發完組件以後,會將組件上傳到倉庫 (Github or other)。而後建立一個 podspec 文件,文件中包含了使用組件時須要加載哪些文件以及從哪裏加載。而後會將這個文件上傳到 CocoaPods(也能夠上傳至私人構建的 spec 管理倉庫)。
組件使用者想要使用某個組件,會在 Podfile 中指定組件的名字、版本、加載源以及更加詳細的信息(例如想要加載某個 commit)。而後執行相關 Pod 命令。
CocoaPods 執行 Pod 命令,而後解析對應的 podspec 文件,肯定須要加載的文件信息並將文件加載到項目工程裏。並建立 Podfile.lock、Manifest.lock、Pods.xcodeproj 等文件。
前面提到 CocoaPods 是開源的,因此咱們能夠把源碼下載下來進行研究。pod install
這個命令定義在 CocoaPods/Core 這 gem 中。
全部命令都是經過 Command
類管理的,執行 pod install
時代碼以下:
# CocoaPods/lib/cocoapods/command/install.rb
module Pod
class Command
class Install < Command
...
def run
verify_podfile_exists!
installer = installer_for_config
installer.repo_update = repo_update?(:default => false)
installer.update = false
installer.install!
end
end
end
end
複製代碼
執行時會先生成一個 installer
實例。而後設置 repo_update
屬性和 update
屬性,最後執行 install
方法。
執行 pod install
命令具體細節前,首先要解析 Podfile。這一過程在初始化 installer
實例時就已經開始:
def installer_for_config
Installer.new(config.sandbox, config.podfile, config.lockfile)
end
複製代碼
pod install 方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
def install!
prepare
resolve_dependencies
download_dependencies
validate_targets
generate_pods_project
if installation_options.integrate_targets?
integrate_user_project
else
UI.section 'Skipping User Project Integration'
end
perform_post_install_actions
end
複製代碼
從方法定義中,能夠看出 pod install
的執行分爲以下幾部:準備階段、解決依賴衝突、下載依賴文件、校驗 target、整合 project 文件、輸出執行結果。下面將按照這個步驟逐步分析。
準備階段代碼以下:
# CocoaPods/lib/cocoapods/installer.rb
def prepare
# Raise if pwd is inside Pods
if Dir.pwd.start_with?(sandbox.root.to_path)
message = 'Command should be run from a directory outside Pods directory.'
message << "\n\n\tCurrent directory is #{UI.path(Pathname.pwd)}\n"
raise Informative, message
end
UI.message 'Preparing' do
deintegrate_if_different_major_version
sandbox.prepare
ensure_plugins_are_installed!
run_plugins_pre_install_hooks
end
end
複製代碼
首先會檢測目錄結構,是否爲可執行 pod 命令的目錄,若是不是直接輸出信息。若是可執行,則作一些準備工做。若是你的 Podfile 中寫了一些 hooks,也會在這裏執行。
這一階段的方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
def resolve_dependencies
plugin_sources = run_source_provider_hooks
analyzer = create_analyzer(plugin_sources)
UI.section 'Updating local specs repositories' do
analyzer.update_repositories
end if repo_update?
UI.section 'Analyzing dependencies' do
analyze(analyzer)
validate_build_configurations
clean_sandbox
end
analyzer
end
複製代碼
根據方法定義,咱們能夠看出這一階段處理的事情:啓動 hooks 並建立一個 analyzer
,而後使用這個 analyzer
更新本地 specs 庫、處理版本依賴。
首先是建立 analyzer
,建立過程當中將 Podfile
和 lockfile
等一些文件信息所有傳入,並在這個類中將這些文件解析。建立 analyzer
代碼以下:
# CocoaPods/lib/cocoapods/installer.rb
def create_analyzer(plugin_sources = nil)
Analyzer.new(sandbox, podfile, lockfile, plugin_sources).tap do |analyzer|
analyzer.installation_options = installation_options
analyzer.has_dependencies = has_dependencies?
end
end
複製代碼
而後是更新本地 specs 庫。從代碼中能夠看出有一個 repo_update?
判斷,也就是說這個標誌位真的時候,纔會更新本地 specs 庫。也就是咱們經常使用的一條命令:
pod repo udpate
複製代碼
最後是處理依賴關係。其中 Podfile
、lockfile
也是使用 Analyzer
這個類中解析。下面是解析方法的定義 :
# CocoaPods/lib/cocoapods/installer/analyzer.rb
def analyze(allow_fetches = true)
validate_podfile! # step1: 解析並校驗 podfile
validate_lockfile_version! # step2: 解析並校驗 lockfile 中的庫的版本
@result = AnalysisResult.new # step3: 新建 result 實例
...
@result.specifications = generate_specifications(resolver_specs_by_target)
@result.targets = generate_targets(resolver_specs_by_target)
@result.sandbox_state = generate_sandbox_state
@result.specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
end
@result.specs_by_source = Hash[resolver_specs_by_target.values.flatten(1).group_by(&:source).map { |source, specs| [source, specs.map(&:spec).uniq] }]
sources.each { |s| @result.specs_by_source[s] ||= [] }
@result
end
複製代碼
最終會將解析結果保存在一個 @result
實例中,進行後面步驟時,會使用這個解析結果。AnalysisResult
類定義以下,註釋我就不翻譯了,看原味的英文更有助於理解具體意思:
# CocoaPods/lib/cocoapods/installer/analyzer/analysis_result.rb
module Pod
class Installer
class Analyzer
class AnalysisResult
# @return [SpecsState] the states of the Podfile specs.
attr_accessor :podfile_state
# @return [Hash{TargetDefinition => Array<Specification>}] the
# specifications grouped by target.
attr_accessor :specs_by_target
# @return [Hash{Source => Array<Specification>}] the
# specifications grouped by spec repo source.
attr_accessor :specs_by_source
# @return [Array<Specification>] the specifications of the resolved
# version of Pods that should be installed.
attr_accessor :specifications
# @return [SpecsState] the states of the {Sandbox} respect the resolved
# specifications.
attr_accessor :sandbox_state
# @return [Array<AggregateTarget>] The aggregate targets created for each
# {TargetDefinition} from the {Podfile}.
attr_accessor :targets
# @return [Hash{TargetDefinition => Array<TargetInspectionResult>}] the
# results of inspecting the user targets
attr_accessor :target_inspections
# @return [Hash{String=>Symbol}] A hash representing all the user build
# configurations across all integration targets. Each key
# corresponds to the name of a configuration and its value to
# its type (`:debug` or `:release`).
def all_user_build_configurations
targets.reduce({}) do |result, target|
result.merge(target.user_build_configurations)
end
end
end
end
end
end
複製代碼
關於 Podfile
的解析過程,有興趣的能夠查看一下 PodfileValidator
類,在目錄 CocoaPods/lib/cocoapods/installer/analyzer/podfile_validator.rb
。
下載依賴文件方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
def download_dependencies
UI.section 'Downloading dependencies' do
create_file_accessors
install_pod_sources
run_podfile_pre_install_hooks
clean_pod_sources
end
end
複製代碼
這個方法中調用了幾個其餘方法。做用分別爲:建立文件存儲器,以便向沙盒裏面寫入數據;下載數據;啓動 hooks;進行清理操做。具體每一個方法的定義,能夠查看文件源碼。這裏主要說一下 install_pod_sources
方法。
install_pod_sources
方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
# Downloads, installs the documentation and cleans the sources of the Pods
# which need to be installed.
#
# @return [void]
#
def install_pod_sources
@installed_specs = []
pods_to_install = sandbox_state.added | sandbox_state.changed title_options = { :verbose_prefix => '-> '.green } root_specs.sort_by(&:name).each do |spec| if pods_to_install.include?(spec.name) if sandbox_state.changed.include?(spec.name) && sandbox.manifest previous = sandbox.manifest.version(spec.name) title = "Installing #{spec.name} #{spec.version} (was #{previous})" else title = "Installing #{spec}" end UI.titled_section(title.green, title_options) do install_source_of_pod(spec.name) end else UI.titled_section("Using #{spec}", title_options) do create_pod_installer(spec.name) end end end end 複製代碼
首先肯定須要 install 的組件。這裏主要針對新加的組件和變動的組件進行 install,至於這些信息是經過 sandbox_state
獲取的。然而 sandbox_state
方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
def sandbox_state
analysis_result.sandbox_state
end
複製代碼
這裏的 analysis_result
就是咱們上一步中解析出的結果,在這裏用到了。
第二步建立 title 配置信息,後面針對變動的組件,會用這個配置標記。相信每一位開發者進行 pod install 操做的時候,都會注意到變動的組件自動標記爲綠色。
最後一步是下載對應文件。這裏分了三種狀況:若是組件已經下載且版本號沒有發生變化,則直接提示 「Using xxx」,以下圖中的 「YYCache」 組件;若是組件已經下載,可是版本號發生了變化,則更新組件並提示 「Installing xxx 版本號 (以前版本號)」,以下圖中的 「AFNetworking」 組件;若是組件第一次下載,則進行下載,並提示 「Installing xxx」,以下圖中的 「YYImage」。
校驗 target 代碼以下:
# CocoaPods/lib/cocoapods/installer.rb
def validate_targets
validator = Xcode::TargetValidator.new(aggregate_targets, pod_targets)
validator.validate!
end
# CocoaPods/lib/cocoapods/installer/xcode/target_validator.rb
def validate!
verify_no_duplicate_framework_and_library_names
verify_no_static_framework_transitive_dependencies
verify_no_pods_used_with_multiple_swift_versions
verify_framework_usage
end
複製代碼
這個方法中,建立了一個 TargetValidator
實例,並調用 validate()
方法進行校驗。這方方法主要分爲如下幾步:
檢測是否有多重引用 framework 或者 library 的狀況。由於一個組件可能分紅多個 subspec,若是不清楚 subspec 中的依賴關係。使用時可能會出現多重引用的狀況。舉個例子,下面是 「網易雲信「 的 podspec 文件,以及其中依賴的兩個組件的 podspec 文件:
# NIMKit.podspec
Pod::Spec.new do |s|
...
s.subspec 'Full' do |cs|
cs.source_files = 'NIMKit/NIMKit/**/*.{h,m}'
cs.dependency 'NIMKit/Core'
cs.dependency 'NIMSDK', '~> 4.9.0'
end
s.subspec 'Lite' do |cs|
cs.source_files = 'NIMKit/NIMKit/**/*.{h,m}'
cs.dependency 'NIMKit/Core'
cs.dependency 'NIMSDK_LITE', '~> 4.9.0'
end
s.subspec 'Core' do |os|
...
end
s.default_subspec = 'Lite'
end
# NIMSDK.podspec
Pod::Spec.new do |s|
...
s.vendored_libraries = '**/Libs/*.a'
s.vendored_frameworks = '**/NIMSDK.framework','**/NIMAVChat.framework'
...
end
# NIMSDK_LITE.podspec
Pod::Spec.new do |s|
...
s.vendored_libraries = 'NIMSDK/Libs/*.a'
s.vendored_frameworks = '**/NIMSDK.framework'
...
end
複製代碼
而後我這樣去引用:
pod 'NIMKit', :subspecs => ['Lite','Full']複製代碼
由於兩個 spec 中都引用了 NIMKit framework,因此執行 `pod install` 的時候就會出現以下問題:
> 這裏仍是不太理解,可能表述有誤。若是清楚請指出,我加以改正。
複製代碼
處理靜態庫傳遞依賴問題。若是 A 組件依賴 B 組件,B 組件中含有經過vendored_libraries加載的靜態庫.a或framewrok。若是 Podfile
中不使用 use_frameworks!
,不會出現任何問題;若是使用 use_frameworks!
,那麼打包的 framework
會將 vendored_libraries
庫中的內容包含進來,這就出現了符號衝突的問題了。若是出現了這種問題,CocoaPods 會報出以下錯誤:
The 'pod-name' target has transitive dependencies that include static binaries: (static_libs.to_sentence)
複製代碼
由於在 swift 中必須使用 `use_frameworks`,因此 swift 中常常會遇到這種問題。解決辦法就是修改 `podspec` 和 `Podfile` 兩個文件:
podspec:
s.dependency 'xxx', '~> 15.2.0'
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/xxx',
'OTHER_LDFLAGS' => '$(inherited) -undefined dynamic_lookup'
}
複製代碼
podfile:
pre_install do |installer|
# workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
def installer.verify_no_static_framework_transitive_dependencies; end
end複製代碼
校驗不一樣 target 所引用的代碼中,若是包含 swift,所使用的 swift 版本是否相同。若是不一樣則會報出以下錯誤:
The following pods are integrated into targets that do not have the same Swift version:{error_messages.join}
複製代碼
當在 swift 中使用時,校驗是否在 Podfile
中是否添加了 use_frameworks!
。若是不添加便會報錯。例如:
Podfile
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
# ignore all warnings from all pods
inhibit_all_warnings!
target 'SwiftTest' do
pod 'AFNetworking','3.0'
pod 'Alamofire', '~> 4.6'
pod 'YYCache'
pod 'YYImage'
pod 'YYImage'
end
複製代碼
[!] Pods written in Swift can only be integrated as frameworks; add `use_frameworks!` to your Podfile or target to opt into using it. The Swift Pod being used is: Alamofire
複製代碼
ps: 在 CocoaPods 1.5 中,已經支持 swift 使用靜態庫,具體可查看 CocoaPods 1.5.0 — Swift Static Libraries . 寫這篇文章的時候還未支持。
依賴文件下載完畢以後,會將這些文件打包成 Pods.xcodeproj
。這一過程方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
# Generate the 'Pods/Pods.xcodeproj' project.
#
def generate_pods_project(generator = create_generator)
UI.section 'Generating Pods project' do
generator.generate!
@pods_project = generator.project
run_podfile_post_install_hooks
generator.write
generator.share_development_pod_schemes
write_lockfiles
end
end
複製代碼
這裏會經過 generator
實例執行 generate!
方法。咱們主要說一下這個方法:
# CocoaPods/lib/cocoapods/installer/xcode/pods_project_generator.rb
def generate!
prepare
install_file_references
install_libraries
integrate_targets
set_target_dependencies
end
複製代碼
這個方法作了這樣幾件事:
Pods.xcodeproj
工程這一系列過程的操做,主要依賴於前面所提到的 CocoaPods/Xcodeproj 組件。
這是最後一個階段,會下載每一個組件的具體源文件,並輸出最終的執行結果。方法定義以下:
# CocoaPods/lib/cocoapods/installer.rb
# Performs any post-installation actions
#
def perform_post_install_actions
unlock_pod_sources
run_plugins_post_install_hooks
warn_for_deprecations
warn_for_installed_script_phases
lock_pod_sources
print_post_install_message
end
複製代碼
這一過程通常是最慢的一個過程。偷懶一下,其中的過程方法我就不一一講解了。看一下最後輸出信息這個方法吧:
def print_post_install_message
podfile_dependencies = podfile.dependencies.uniq.size
pods_installed = root_specs.size
title_options = { :verbose_prefix => '-> '.green }
UI.titled_section('Pod installation complete! ' \
"There #{podfile_dependencies == 1 ? 'is' : 'are'} #{podfile_dependencies} " \
"#{'dependency'.pluralize(podfile_dependencies)} from the Podfile " \
"and #{pods_installed} total #{'pod'.pluralize(pods_installed)} installed.".green,
title_options)
end
複製代碼
也就是咱們常見的輸出結果:
執行一次 pod install
的過程到此結束了。若是你大體讀一遍源碼,執行 pod install
再遇到問題時,能夠快速判定問題緣由並修復。pod update
和 pod install
仍是有一些差異的,有興趣的同窗能夠讀一下 pod update
的源碼。我這裏就不在寫了,就算你讀不吐我都快寫吐了。
這裏假設你什麼都沒有安裝,從 0 開始。若是你已經安裝了某些東西,能夠跳過。
安裝 rvm
curl -L get.rvm.io | bash -s stable
source ~/.bashrc
source ~/.bash_profile
複製代碼
查看 rvm 版本
rvm -v
複製代碼
rvm 1.29.3 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]
複製代碼
查看可安裝 Ruby 版本
rvm list known
複製代碼
安裝一個版本,我通常選最高,這裏是 2.4.1
rvm install 2.4.1複製代碼
由於你後面可能會稀裏糊塗裝不少版本,因此設置這個版本爲默認版本
rvm use 2.4.1 --default複製代碼
// 安裝 CocoaPods
sudo gem install cocoapods
// 安裝本地庫,須要等待很長時間
pod setup
複製代碼
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer複製代碼
pod search [一個組件]複製代碼
// 查看當前安裝的全部 CocoaPods 版本
gem list –local | grep cocoapods
// 當前使用 pod 版本
pod –version
// 更新到最新穩定版本
sudo gem install cocoapods
// 更新到一個 pre-release 版本
sudo gem install cocoapods –pre
// 安裝指定版本
sudo gem install cocoapods -v [版本號]
// 移除 CocoaPods,若是你安裝多個,會列出一個 list 讓你選擇刪除那個。若是隻安裝一個,也會給你提示,問你是否肯定刪除。
sudo gem uninstall cocopods
// 移除指定版本
sudo gem uninstall cocopods -v [版本號]
// 使用指定版本執行命令
pod 1.3.1 install
複製代碼
// 打開一新的工程,執行命令
pod init
// Podfile 中添加
pod ‘AFNetworking’
// install
pod install複製代碼
pod install –verbose複製代碼
// 不添加組件名則更新全部
pod update [組件名]複製代碼
pod repo update複製代碼
// –verbose 可省略
pod install –verbose –no-repro-update
pod update –verbose –no-repro-update
複製代碼
pod lib lint –allow-warnings複製代碼
pod spec lint複製代碼
// [reponame] 通常能夠在路徑 ~/.cocoapods/repo 下查看,選擇你須要的 name.
pod repo push [reponame] [name.podspec] –verbose –sources=master,[reponame] –use-libraries –allow-warnings複製代碼
Podfile Syntax Reference v1.4.0
source 'https://github.com/CocoaPods/Specs.git' # 組件依賴文件所存放倉庫,根據需求可引入多個
source 'https://github.com/artsy/Specs.git'
platform :ios, '8.0' #
inhibit_all_warnings! # 忽視引用的代碼中的警告
workspace 'CocoaPodsDemo' # 指定生成的 workspace 名字
def common_pods # 若是有多個 target,能夠將公共部分進行 def 定義再引入
pod 'xxx'
end
target 'CocoaPodsDemo' do
project 'DemoProject' # 可用於指定實際的工程
use_frameworks! # 是否以 framework 形式引入。swift 必須有這個關鍵字
common_pods # 公共引入的組件
pod 'SSipArchive', :inhibit_warnings => true # 屏蔽某個 pod 的 warning
pod 'AFNetworking', '3.2' # 使用 3.2 版本
pod 'YYCache', '~> 0.3' # pod update 時最高升級到 < 1.0,不包括 1.0
# Build 環境配置
pod 'PonyDebugger', :configurations => ['Debug', 'Beta']
pod 'PonyDebugger', :configuration => 'Debug'
# 使用具體的某個 subspec
pod 'QueryKit/Attribute'
pod 'QueryKit', :subspecs => ['Attribute', 'QuerySet']
# 引用本地組件
pod 'AFNetworking', :path => '~/Documents/AFNetworking'
# 使用具體倉庫
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git'
# 使用具體倉庫具體分支
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :branch => 'dev'
# 使用具體倉庫的某個 tag
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :tag => '0.7.0'
# 使用具體倉庫的某個 commit
pod 'AFNetworking', :git => 'https://github.com/gowalla/AFNetworking.git', :commit => '082f8319af'
# 使用指定路徑的 spec 文件
pod 'JSONKit', :podspec => 'https://example.com/JSONKit.podspec'
target 'ShowsApp' do
pod 'ShowsKit'
# Has its own copy of ShowsKit + ShowTVAuth
target 'ShowsTV' do
pod 'ShowTVAuth'
end
# Has its own copy of Specta + Expecta
# and has access to ShowsKit via the app
# that the test target is bundled into
target 'ShowsTests' do
# inherit! 有三種類型:':complete' 繼承父級全部行爲;':none' 什麼行爲都不繼承;':search_paths' 繼承父級的 search paths
inherit! :search_paths
pod 'Specta'
pod 'Expecta'
end
end
end
# hook 配置, 在 preparing 階段後,install 以前
pre_install do |installer|
end
# hook 配置,在 pod install 以後,可用於修改工程配置等
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
複製代碼
Podspec Syntax Reference v1.4.0
Pod::Spec.new do |spec|
# 組件基本信息配置
#
# 組件名
spec.name = 'Reachability'
# 組件版本號,命名規則遵循 [semantic versioning](https://semver.org/)
spec.version = '3.1.0'
# 許可證
spec.license = { :type => 'BSD' }
# 倉庫主頁
spec.homepage = 'https://github.com/tonymillion/Reachability'
# 一個做者用 spec.author = 'Darth Vader'
spec.authors = { 'Tony Million' => 'tonymillion@gmail.com' }
# 組件概述
spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and OS X.'
# 組件源碼地址
spec.source = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0' }
# 組件平臺支持
#
# 支持單平臺使用
spec.platform = :osx, '10.8'
spec.platform = :ios
# 支持多平臺使用
spec.ios.deployment_target = '6.0'
spec.osx.deployment_target = '10.8'
# Build settings
#
spec.dependency 'AFNetworking', '~> 1.0' # 組件依賴的第三方庫
spec.requires_arc = false # 是否要求 ARC 環境
spec.requires_arc = ['Classes/*ARC.m', 'Classes/ARC.mm']
spec.frameworks = 'QuartzCore', 'CoreData' # 組件引用的 framework spec.weak_frameworks = 'Twitter', 'SafariServices' # 組件弱引用的 framework
spec.libraries = 'xml2', 'z' # 組件引用的 library
... 更多請看官方文檔
# File patterns
#
spec.source_files = 'Classes/**/*.{h,m}' # 接入方使用組件時,引入的源文件,正則匹配
spec.public_header_files = 'Headers/Public/*.h' # 引入的共有頭文件
spec.private_header_files = 'Headers/Private/*.h' # 引入的私有頭文件
spec.vendored_frameworks = 'MyFramework.framework'# 引入的 framework
spec.vendored_libraries = 'libProj4.a' # 引入的 library
# 以 bundle 形式引入的資源
spec.resource_bundles = {
'MapBox' => ['MapView/Map/Resources/*.png'],
'OtherResources' => ['MapView/Map/OtherResources/*.png']
}
# 直接引入資源
spec.resources = ['Images/*.png', 'Sounds/*']
... 更多請看官方文檔
# Subspecs
#
# 將組件分爲多個子組件,接入方能夠根據需求只接入幾個子組件,減小包體積
subspec 'Twitter' do |sp|
sp.source_files = 'Classes/Twitter'
end
# 測試組件
spec.test_spec do |test_spec|
test_spec.source_files = 'NSAttributedString+CCLFormatTests.m'
test_spec.dependency 'Expecta'
end
# 默認子組件。也就是當接入方不做區分時,直接使用組件名引入時,所引入子組件
spec.default_subspec = 'Core'
# 多平臺支持
#
spec.ios.source_files = 'Classes/ios/**/*.{h,m}'
spec.osx.source_files = 'Classes/osx/**/*.{h,m}'
複製代碼
Cocopods 基本使用內容就這些。具體能夠查看官方文檔中 Reference 這一章節。
這裏是一些常常遇到的問題。不是很全面,但願對你有幫助。
由於執行 pod install
以後,下載完的文件會經過使用 CocoaPods/Xcodeproj 合成一個 Project。Xcode 經過使用 Workspace 管理多個 Project,使各個 Project 之間能夠相互引用。爲了使工程中的文件可以引用組件中的文件,因此這裏須要以 Workspace 形式打開。
這是 官方文檔 中描述的一個經典問題。
pod install: 優先安裝 Podfile 中改變的組件,並優先遵循 Podfile 中的版本號,其次遵循 Podfile.lock 中的版本號。若是使用的 Podfile 中版本號,會將新的版本號更新到 Podfile.lock 中。
pod update [PODNAME]: 會根據當前 Podfile 規則更新組件。若是 Podfile 中沒有指定版本號,並不會遵循 Podfile.lock,而是會拉取最新版本,並更新 Podfile.lock。
官方建議:
pod install
,不要使用 pod update
去下載一個新的組件,避免跟新其餘 pod 的版本。pod update [PODNAME]
。pod update
,避免沒必要要的更新。swift 版本問題
問題:
解決方案:
2.3, run終端輸入:echo 「2.3」 > .swift-version
驗證出現警告問題
pod spec lint xxx.podspec --allow-warning
複製代碼
找不到頭文件
pod spec lint --allow-warnings --use-libraries
複製代碼
固然 CocoaPods 還有不少問題,這裏就不一一列舉了,若是遇到問題自行 Google 吧,不少問題都已經有了答案。
CocoaPods 的相關知識,就總結到這裏。花時間如仔細研究一下,仍是能學到不少東西的。這樣在從此的項目開發中遇到問題後,能夠快速定位並解決,提升開效率。