做者: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 的相关知识,就总结到这里。花时间如仔细研究一下,仍是能学到不少东西的。这样在从此的项目开发中遇到问题后,能够快速定位并解决,提升开效率。