Cocoapods 的安装、使用及其配置

项目中有第三方库?

不用 Cocoapods 真是你的损失呐。

Basic

如果你只是想用 Cocoapods 把第三方库导入你的工程,本章内容目的就是以最快速度让你把 Cocoapods 应用到你的项目中。

Installation

Cocoapods 基于 Ruby,OS X 已经安装好 Ruby。限于国内的网络,此处先修改 RubyGems 源的地址。

$ gem sources --remove https://rubygems.org/
$ gem sources -a http://ruby.taobao.org/

执行完毕后,验证是否修改成功。

$ gem sources -l

如果显示如下信息代表修改成功。

*** CURRENT SOURCES ***
http://ruby.taobao.org/

接下来安装 Cocoapods

$ sudo gem install cocoapods

Usage

如果你还没装 Alcatraz,那请你先安装 Alcatraz。

curl -fsSL https://raw.github.com/supermarin/Alcatraz/master/Scripts/install.sh | sh

进入你要添加第三方库的工程,按command + shift + 9调出 Alcatraz 搜索界面,搜索 Cocoapods 并安装。

安装完毕后,重启 Xcode,如下图点击创建 Podfile。

AFNetworking为例,在 Podfile 文件中写入并保存。

platform :ios, "7.0"
pod "AFNetworking"

这时 Cocoapods 插件已经可以选择安装了。

点击安装

提示重新启动并打开 .workspace文件,现在你已经可以愉快的引用 AFNetworking.h咯!

Advanced

本章内容有助于你提高对 Cocoapods 更深层次的理解。

Commands

1. pod install

根据在 Podfile 中配置好的第三方库信息来安装对应的库。

如果存在 Podfile.lock 文件则根据 Podfile.lock 中锁定的版本进行安装。

每次更新了Podfile文件时,都需要重新执行该命令,以便重新安装Pods依赖库。

2. pod update

很多情况下,Podfile 中的第三方库信息格式并没有指定某个库的具体版本,那么在执行 pod update后,第三方库都会更新到最新版本且 Podfile.lock 会一同更新。

3. pod search

执行

$ pod search AFNetworking

得到如下信息:

-> AFNetworking (2.5.4)
A delightful iOS and OS X networking framework.
pod 'AFNetworking', '~> 2.5.4'
- Homepage:
https://github.com/AFNetworking/AFNetworking
- Source:
https://github.com/AFNetworking/AFNetworking.git
- Versions: 2.5.4, 2.5.3, 2.5.2, 2.5.1, 2.5.0, 2.4.1,
2.4.0, 2.3.1, 2.3.0, 2.2.4, 2.2.3, 2.2.2, 2.2.1,
2.2.0, 2.1.0, 2.0.3, 2.0.2, 2.0.1, 2.0.0, 2.0.0-RC3,
2.0.0-RC2, 2.0.0-RC1, 1.3.4, 1.3.3, 1.3.2, 1.3.1,
1.3.0, 1.2.1, 1.2.0, 1.1.0, 1.0.1, 1.0, 1.0RC3,
1.0RC2, 1.0RC1, 0.10.1, 0.10.0, 0.9.2, 0.9.1, 0.9.0,
0.7.0, 0.5.1 [master repo]
- Subspecs:
- AFNetworking/Serialization (2.5.4)
- AFNetworking/Security (2.5.4)
- AFNetworking/Reachability (2.5.4)
- AFNetworking/NSURLConnection (2.5.4)
- AFNetworking/NSURLSession (2.5.4)
- AFNetworking/UIKit (2.5.4)

选择你的目的版本配置到 Podfile 文件中。

4. pod setup

在本地 Cocoapods 会保存一个 Pods 依赖库的 tree,这个 tree 和服务端的 tree 可能会不同步。因为大量第三方库的作者每天都在维护自己的库,会更新库的版本,执行

$ pod setup

可以让本地依赖库的 tree 与服务端同步。

Usage

上一章中,介绍了通过 Xcode 插件来实现利用 Cocoapods 引入第三方库的方法。然而很多程序员觉得还是用命令行界面去操作这一切才更 Cool。

下文以 YOUR_PROJECT代替项目路径为例,介绍下命令行中 Cocoapods 的使用方法。

$ cd YOUR_PROJECT
$ touch Podfile

打开你的 Xcode 或者 其他编辑器也行,开始编辑 Podfile,此处依旧以 AFNetworking为例

platform :ios, "7.0"
pod "AFNetworking"

编辑好后,还在YOUR_PROJECT路径下,执行

$ pod install

正常情况下将会出现如下提示

Updating local specs repositories
Analyzing dependencies
Downloading dependencies
Installing AFNetworking (2.5.4)
Generating Pods project
Integrating client project
Sending stats

然后打开你项目的 .workspace文件,就可以轻松的使用第三方库了。

Principle

为什么我们执行这几条指令就可以使用第三方库了?

首先我们注意到,用 Cocoapods 安装第三方库后,不再打开原工程文件,而是打开一个.workspace的文件。实际上在 Cocoapods 为我们安装第三方库的过程中,它做了如下几件事:

  • 将目的第三方库以 target 的方式导入
  • 将这些 target 组合成一个名为 Pods 的工程
  • 生成 libPods.a 静态库供原工程使用
  • 原工程和第三方库生成的 Pods 工程组合成新的 .workspace

Podfile

Podfile 就是用来描述一个或者多个 Xcode 工程中 targets 和第三方库的依赖关系。默认情况下只在用户工程的第一个 target中生效。

1. 多个 target 共用依赖 Pods

以两个 target 分别为 MyApp1 和 MyApp2 为例,用link_with即可。

platform :osx, '10.7'
link_with 'MyApp1', 'MyApp2'
pod 'AFNetworking', '~> 2.0'
pod 'Objection', '0.9'

2. 多个 target 依赖不同 Pods

第一个名为 MyApp1 的 target 依赖于 ObjectiveSugar 和 Artsy+UILabels,第二个名为 MyApp2 的 target 依赖于 OCMock。

platform :ios, '8.0'
target :MyApp1 do
pod 'ObjectiveSugar', '~> 0.5'
pod 'Artsy+UILabels', '~> 1.0'
end
target :MyApp2 do
pod 'OCMock', '~> 2.0.1'
end

3. 关于版本

可以不写版本,也可以指定某个版本,当然也可以使用一些逻辑运算符。

  • '> 0.1' 比 0.1 高的所有版本
  • '>= 0.1’ 高于或者等于 0.1 的所有版本
  • '< 0.1’ 低于 0.1 的所有版本
  • '<= 0.1' 低于或者等于 0.1 的所有版本

CocoaPods 中有个特殊的逻辑运算符 ~>:

  • '~> 0.1.2’ 包含 0.1.2 这个版本,最高不超过 0.2,不包括 0.2 或者更高版本
  • '~> 0.1’ 包含 0.1 这个版本,最高不超过 1.0,不包括 1.0 或者更高版本
  • '~> 0’ 版本 0 或者更高,和没写一样。

更多关于版本的相关信息和规则,下方扩展阅读:

Podfile.lock

Issue

很多人都有一种困惑,从 GitHub 行 clone 下来别人的工程,看 Podfile 中对 AFNetworking这个第三方库的描述是这样

pod "AFNetworking", '~> 2.5.2'

而经过

pod search afnetworking

发现当前最新的版本已经是 2.5.6

这时当你在项目目录下执行了

pod install

按理说应该安装 2.6.0 版本以内的最近版本,也就是 2.5.6,实际上发现还是安装了 2.5.2 ,这就是 Podfile.lock 存在的意义。

Necessity

假如没有 Podfile.lock,那么在团队开发中绝对是一种灾难。假设 A 君和 B 君在协作开发同一个项目。A君作为这个项目的创建者,在 Podfile 中对AFNetworking的描述是

pod "AFNetworking", '~> 2.5.2'

当 B 君 check out 这个项目时,AFNetworking这个库已经更新到了 2.5.5,那他在

pod install

之后,他本地的这个项目就会依赖于 2.5.5 版本的 AFNetworking。如果这几代版本更迭修改了一些方法的名称,那项目里将会各种 error。

很多人会说,那直接锁定某个版本的AFNetworking,不就不会出现这个问题了?但是开源库的优化是随时进行的,同时还伴随修复 Bug 等操作,所以锁定某个版本的行为是不可取的。

好在有 Podfile.lock,在 A 君第一次执行

pod install

之后,会在 Podfile.lock 中生成如下描述

PODS:
- AFNetworking (2.5.2):
- AFNetworking/NSURLConnection (= 2.5.2)
- AFNetworking/NSURLSession (= 2.5.2)
- AFNetworking/Reachability (= 2.5.2)
- AFNetworking/Security (= 2.5.2)
- AFNetworking/Serialization (= 2.5.2)
- AFNetworking/UIKit (= 2.5.2)
- AFNetworking/NSURLConnection (2.5.2):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/NSURLSession (2.5.2):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/Reachability (2.5.2)
- AFNetworking/Security (2.5.2)
- AFNetworking/Serialization (2.5.2)
- AFNetworking/UIKit (2.5.2):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
DEPENDENCIES:
- AFNetworking (~> 2.5.2)
SPEC CHECKSUMS:
AFNetworking: fefbce9660acb17f48ae0011292d4da0f457bf36
COCOAPODS: 0.38.2

这时 B 君 check out 此项目之后,执行

pod install

Cocoapods 会安装在 Podfile.lock 中描述的版本,而不会按照 Podfile 中的逻辑运算安装最新的 2.5.5 。

在协同开发的时候,记得要一并同步 Podfile.lock,它会保证在 Podfile 中描述逻辑允许的情况下,锁定安装 Podfile.lock 描述中的版本。

只有在

pod update

之后,才会检查最新的版本,并且重写 Podfile.lock 中对第三方库的版本描述。

通常情况下,我们无必要手动修改 Podfile.lock 中的内容,但是将它从.gitignore中移除是十分必要的。

Q & A

一些可能遇到的问题和对应的解决答案,我踩过的坑,你就别踩了。

Q1: 用 gem 安装 Cocoapods 提示 gem 版本过老怎么办

A1: 请升级 gem

$ sudo gem update --system

Q2: 如何升级 Cocoapods 的版本?

A2: 升级 Cocoapods 的版本其实和安装是一样的

$ sudo gem install cocoapods

Q3: 多个版本的 Cocoapods 如何卸载?

A3: 终端输入

$ gem list

如果你安装(也可能是升级导致)了多个版本的 Cocoapods,本例中如图,安装了 0.38.2 和 0.36.3 两个版本。想卸载其中的旧版本,0.36.3

$ sudo gem uninstall cocoapods

选择 1,更低的版本就被卸载掉了。

或者直接执行如下命令,老版本的都都被卸载了。

$ sudo gem clean

Q4: 我怎么搜索不到某个第三方库的最新版本?

A4:可能是你的 Cocoapods 的版本低或者你本地的依赖库 tree 较旧所致。参见 Q2pod setup 的使用。

Q5: 错误ERROR: While executing gem … (Gem::FilePermissionError) You don’t have write permissions for the /Library/Ruby/Gems/2.0.0 directory

A5: 这个错误往往出现在安装 Cocoapods 或者删除某个版本的 Cocoapods 的情况下,简单粗暴就是修改权限

sudo chmod 777 /Library/Ruby/Gems/2.0.0

Q6: 为什么 Pods 导入成功了但是无法引用头文件?

A6: Cocoapods 把第三方库以多个 target 形式组成一个名为 Pods 的工程,编译为静态库,所以我们其实可以像引用系统框架一样来引入他们的头文件。

#import <AFNetworking>

如果一定要使用双引号的形式,那就设置目标项目 target 中的 User Header Search Paths,双击此选项,添加一个 ${SRCROOT}的键,值设定为recursive,这样就可以递归搜索全部目录。