Cocoapods是 OS X 和 iOS 下的一个第三方库管理工具。你能使用CocoaPods添加被称作“Pods”的依赖库,并轻松管理它们的版本,而不用考虑当前的时间和开发环境。

Cocoapods意义体现在两个方面。首先,引入第三方库无可避免地要进行各种各样的配置。对于Objective-C的初级开发者来说,项目配置可是一件艰巨的任务。在配置编译阶段和链接器选项的过程中,极有可能引入许多人为的错误。而CocoaPods简化了这一切,它能自动配置编译选项,拯救了开发者。

其次,使用CocoaPods可以很方便地查找新的第三方库。当然,这可不是说让你七拼八凑别人代码而开发出一个“移栽”应用。而是让你找到真正好用的库,缩短你的开发周期,提升你的代码质量。

接下来,我们将通过分析pod安装的过程,一步步揭示CocoaPods背后的技术。

核心组件

CocoaPods是用ruby写的,并划分成了若干个Gem包。CocoaPods在解析执行过程中最重要的几个包的路径分别是:CocoaPods/CocoaPods、 CocoaPods/Core 和 CocoaPods/Xcodeproj

CocoaPods / CocoaPod

这是面向用户的组件,每当你执行一个pod命令时,这个组件将被激活。它包括了所有实用CocoaPods的功能,并且还能调用其他gem包来执行任务。

CocoaPods / Core

Core gem提供了与CocoaPods相关的文件(主要是Podfile和podspecs)的处理。

Podfile

Podfile用于配置项目所需要的第三方库。它能被高度定制,所以你可以尽可能地给它添加你想要的特性。如果您还想对Podfile了解更多的话,请查看Podfile指南(地址 http://guides.cocoapods.org/syntax/podfile.html)。

Podspec

.podspec文件描述了一个库将怎样被添加进工程中。.podspec文件可以标识该第三方库所需要的源码文件、依赖库、编译选项,以及其他第三方库需要的配置。

CocoaPods / Xcodeproj

这个包负责工程文件直接关系的处理。它能创建以及修改.xcodeproj文件和.xcworkspace文件。它也可以作为一个独立的包使用,当你要编写修改项目文件的脚本时,可以考虑使用CocoaPods/Xcodeproj。

运行 pod install 命令

pod install的执行引发了很多操作。了解底层运行过程最简单的方式就是给pod install语句添加 –verbose 参数。现在,运行

1
pod install --verbose

将会出现以下执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Analyzing dependencies
 
Updating spec repositories
Updating spec repo `master`
$ /usr/bin/git pull
Already up-to-date.
 
Finding Podfile changes
- AFNetworking
- HockeySDK
 
Resolving dependencies of `Podfile`
Resolving dependencies for target `Pods' (iOS 6.0)
- AFNetworking (= 1.2.1)
- SDWebImage (= 3.2)
- SDWebImage/Core
 
Comparing resolved specification to the sandbox manifest
- AFNetworking
- HockeySDK
 
Downloading dependencies
 
-> Using AFNetworking (1.2.1)
 
-> Using HockeySDK (3.0.0)
- Running pre install hooks
- HockeySDK
 
Generating Pods project
- Creating Pods project
- Adding source files to Pods project
- Adding frameworks to Pods project
- Adding libraries to Pods project
- Adding resources to Pods project
- Linking headers
- Installing libraries
- Installing target `Pods-AFNetworking` iOS 6.0
- Adding Build files
- Adding resource bundles to Pods project
- Generating public xcconfig file at `Pods/Pods-AFNetworking.xcconfig`
- Generating private xcconfig file at `Pods/Pods-AFNetworking-Private.xcconfig`
- Generating prefix header at `Pods/Pods-AFNetworking-prefix.pch`
- Generating dummy source file at `Pods/Pods-AFNetworking-dummy.m`
- Installing target `Pods-HockeySDK` iOS 6.0
- Adding Build files
- Adding resource bundles to Pods project
- Generating public xcconfig file at `Pods/Pods-HockeySDK.xcconfig`
- Generating private xcconfig file at `Pods/Pods-HockeySDK-Private.xcconfig`
 
 - Generating prefix header at `Pods/Pods-HockeySDK-prefix.pch`
 
- Generating dummy source file at `Pods/Pods-HockeySDK-dummy.m`
- Installing target `Pods` iOS 6.0
- Generating xcconfig file at `Pods/Pods.xcconfig`
- Generating target environment header at `Pods/Pods-environment.h`
- Generating copy resources script at `Pods/Pods-resources.sh`
- Generating acknowledgements at `Pods/Pods-acknowledgements.plist`
- Generating acknowledgements at `Pods/Pods-acknowledgements.markdown`
- Generating dummy source file at `Pods/Pods-dummy.m`
- Running post install hooks
- Writing Xcode project file to `Pods/Pods.xcodeproj`
- Writing Lockfile in `Podfile.lock`
- Writing Manifest in `Pods/Manifest.lock`
Integrating client project

整个过程中执行了很多操作,不过把它们分解之后,会发现它们都很简单。让我们逐步来分析。

阅读Podfile文件

你是否吐槽过Podfile的语法太过诡异,其实这是ruby的语法而不是OC。相较而言,Podfile要比现有的其他格式更加简单好用一些。

安装的第一步是要弄清楚哪些第三方库被显式或隐式地声明了。CocoaPods加载podspecs文件时,获取了第三方库的名称及版本列表。Podsspecs文件存储在本地,路径为~/.cocoapods。

版本控制和冲突

CocoaPods使用语义版本命名约定来解决对版本的依赖。由于冲突解决系统建立在非重大更改的补丁版本之间,这使得解决依赖关系要容易得多。举个栗子,两个完全不同的第三方库同时依赖CocoaLumberjack。它们其中一个依赖的版本是2.3.1,而另一个则为2.3.3,解析器可以自动使用较新的版本,在这里则是2.3.3,因为这可以与2.3.1向后兼容。

但这并不总是有效。有许多第三方库还并不支持这个约定,这让解决方案变得非常复杂。

当然,总是会有一些冲突需要手工解决。如果一个第三方库依赖CocoaLumberjack 1.2.5,而另一个依赖CocoaLumberjack 2.3.1,最后只能靠调用这两个第三方库的用户来手动地决定CocoaLumberjack的版本了。

加载源码

CocoaPods执行的下一个步骤是加载源代码。每个.podspec文件都包含了源代码的索引,这些索引一般指向了一个git地址或者git tag。它们以commit SHA码的方式存储在 ~/Library/Caches/CocoaPods中。而在这些路径中创建文件则由 Core 包负责。

源代码将依照Podfile、.podspec和缓存文件的信息下载到相应的第三方库路径。

生成Pods.xcodeproj

每次pod install 执行后并且检测到改动时,Pods.xcodeproj文件将呗Xcodeproj gem更新。如果Pods.xcodeproj文件不存在,则会以默认配置生成,若已存在,则Pods.xcodeproj会使用现有的配置。

安装第三方库

当Cocoapods向项目中增加了一个第三方库的时候,不仅仅是将添加代码这么简单。由于每个第三方库有不同的target,所以每次添加第三方库时,都只有几个文件被添加。每个源代码都需要:

  • 一个包含编译选项的.xcconfig文件
  • 一个同时拥有编译设置和CocoaPods默认配置的私有.xcconfig文件
  • 编译所必须的prefix.pch文件
  • 另一个编译必须的文件dummy.m

一旦每个pod的target都完成了以上步骤,整个Pods的Target就会被创建。这增加了相同的文件,与另外几个。如果有源代码中包含了资源bundle,向app的target中添加bundle的方式将写入Pods-Resources.sh。还有一个叫Pods-environment.h的文件,文件中含有许多检查组件是否来自pod的宏定义。最后,将生成两个确认文件,一个.plist文件,一个用于给用户查阅许可信息的markdown文件。

写入到磁盘

直到现在,许多已完成的过程都使用的是内存中的对象。为了让这些过程的结果可重复被使用,我们需要将所有结果都记录在一个文件中。所以Pods.xcodeproj和另外两个非常重要的文件:Podfile.lock和Manifest.lock都将被写入磁盘。

Podfile.lock

这是CocoaPods创建的最重要的文件之一。它记录了需要被安装的pod的每个已安装的版本。如果你想知道已安装的pod是哪个版本,可以查看这个文件。推荐将Podfile.lock文件加入到版本控制中,这有助于整个团队的一致性。

Manifest.lock

这是每次运行pod install时创建的Podfile.lock文件的副本。如果你见过“沙盒文件和Podfile.lock文件不同步”的错误,这个错误就是因Manifest.lock文件和Podfile.lock文件不一样引起。由于Pods所在的目录并不总在版本控制之下,这样可以保证开发者运行app之前都能更新他们的pods,否则app可能会crash,或者在一些不太明显的地方编译失败

xcproj

如果您已经依照我们的建议在系统上安装了xcproj,它会将您的Pods.xcodeproj文件转换成就旧有ASCII格式的plist文件。为什么要这么做呢?因为Xcode所依赖和使用的plist在很久以前就已经不被其他软件支持了。如果没有xcproj,你的Pods.xcodeproj文件将会以XML格式的plist文件存储,当你用Xcode打开它时,它会被改写,造成大量的文件冲突。

运行结果

运行pod install的最终结果是许多文件被添加到你的工程和系统中。这个过程通常只需要几秒钟。当然没有Cocoapods这些事也都可以完成。只不过所花的时间就不仅仅是几秒而已了。

旁注:持续集成

CocoaPods和持续集成在一起非常融洽。虽然持续集成很大程度上取决于你的项目配置,但Cocoapods依然能很容易地对项目进行编译。

Pods文件夹已加入版本控制的持续集成

如果包括Pods文件夹的一切东西都在版本控制之中,那么你不需要特别做什么就能够持续集成。由于编译时必须指定一个scheme,所以只需要保证使用了正确的scheme即可。

没有Pods文件夹的持续集成

如果你的Pods文件夹没有被纳入版本控制之中,那么你需要一些额外的步骤来保证持续集成的顺利进行。最起码,Podfile文件要放入版本控制之中。另外强烈建议将生成的.xcworkspace文件和Podfile.lock文件纳入版本控制,这样不仅简单方便,更能保证所使用的Pod是正确的版本。

一旦配置完毕,让CocoaPods在CI上正确运行的关键是保证每次编译之前都执行了pod install。在大多数系统中,譬如Jenkins或者Travis,你只用把“pod install”定义为一个编译步骤即可(实际上,Travis会自动执行pod install)。随着Xcode Bot的发布,我们还没有找到能像书写的这么流畅的解决方案,不过我们正朝着解决方案努力,一旦成功,我们将会立即分享。

结束语

CocoaPods简化了OC的开发流程,我们的目标是让第三方库更容易被发现和添加。了解CocoaPods的原理能让你做出更好的App。我们沿着CocoaPods的整个流程一步步执行,从载入specs文件和源代码、创建.xcodeproj文件和所有组件到将所有文件写入磁盘。所以接下来,我们运行 pod install –verbose,静静观察CocoaPods的魔力如何显现。

原文链接: Michele Titolo   翻译: 伯乐在线programmer.du
译文链接: http://blog.jobbole.com/53365/

[转]iOS系列译文:深入理解 CocoaPods的更多相关文章

  1. iOS系列译文:整洁的表视图代码

    本文由 伯乐在线 - christian 翻译自 Florian Kugler.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 表视图是一个非常万能的iOS应用程序构建模块.因此,有很多与表视图直 ...

  2. iOS系列译文:自定义Collection View布局

    原文出处: Ole Begemann   译文出处: 黄爱武(@answer-huang).欢迎加入技术翻译小组. UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一 ...

  3. iOS系列 基础篇 03 探究应用生命周期

    iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本 ...

  4. iOS系列 基础篇 07 Action动作和输出口

    iOS系列 基础篇 07 Action动作和输出口 目录:  1. 前言及案例说明 2. 什么是动作? 3. 什么是输出口? 4. 实战 5. 结尾 1. 前言及案例说明 上篇内容我们学习了标签和按钮 ...

  5. 【Flask-RESTPlus系列】Flask-RESTPlus系列译文开篇

    0x00 背景介绍 因为工作上的需要,最近开始研究Python中实现Restful API的框架和工具包.之前粗略学习过Flask,由于它比较轻量级,感觉用它来实现Restful API再适合不过了. ...

  6. iOS依赖库管理工具之CocoaPods

    CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具.利用 CocoaPods,可以定义自己的依赖关系库 (称作 pods),并且随着时间的变化,在整个开发环境中对第 ...

  7. [Android开发学iOS系列] 工具篇: Xcode使用和快捷键

    [Android开发学iOS系列] 工具篇: Xcode使用和快捷键 工欲善其事必先利其器. 编辑 Cmd + N: 新建文件 Option + Cmd + N: 新建文件夹 Cmd + / : 注释 ...

  8. [Android开发学iOS系列] Auto Layout

    [Android开发学iOS系列] Auto Layout 内容: 介绍什么是Auto Layout. 基本使用方法 在代码中写约束的方法 Auto Layout的原理 尺寸和优先级 Auto Lay ...

  9. iOS系列教程 目录 (持续更新...)

      前言: 听说搞iOS的都是高富帅,身边妹子无数.咱也来玩玩.哈哈. 本篇所有内容使用的是XCode工具.Swift语言进行开发. 我现在也是学习阶段,每一篇内容都是经过自己实际编写完一遍之后,发现 ...

随机推荐

  1. Nginx 相关介绍(Nginx是什么?能干嘛?个人觉得写得比较好的文章,转载过来)

    Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器.基于REST架构风格,以统一资源描述符(Unifor ...

  2. java-tip-HashMap

    HashMap的基本查找过程: 先使用key.hashCode()生成哈希值,根据哈希值来确定key存放的位置 找到key在数组中的位置后,再使用key.equals()方法来找到指定的key. 1. ...

  3. 764. Largest Plus Sign最大的dfs十字架

    [抄题]: 求挖掉一些区域后,能允许出现的最大十字架 In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except t ...

  4. Tftp上传、下载

    上传 tftp -g -r filename serverip 下载 tftp -p -l filename serverip

  5. 怎样在本地电脑上连接另外一台电脑上的mysql数据?(代码示例)

    基本上有两种方式: 1,使用MYSQL的管理工具,可以远程连接,比如用导航猫系列的,只要知道对方IP,然后就可以自己输入账号密码连接了. 2,使用代码连接. Java代码示例: package com ...

  6. Java研发书单

    Java研发书单 计算机基础:<深入理解计算机系统><计算机网络> 网络方面:<TCP/IP协议卷一><unix网络编程卷一>(部分章节,JAVA主要是 ...

  7. jquery页面初始化控件时间

    this.InitControlTime = function () { if ($("#txt_Id_").val() == "") { var today ...

  8. mybatis 存储过程调用

    接口 UserInfoMapper.java xml   UserInfoMapper.xml 如何关联 <?xml version="1.0" encoding=" ...

  9. iPhone Development – core data relationships tutorial part 1

    I’m going to start a short series on Core Data relationships and maybe throw in some general Core Da ...

  10. Android开发之深入理解NFC(一)

    深入理解NFC NFC(Near field communication,近场通信)也叫做近距离无线通信技术. 从原理来说,NFC和wifi类似,二者都利用无线射频技术来实现设备之间的通信. 但是,和 ...