objc系列译文(6.4):深入理解 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的魔力如何显现。

时间: 2024-08-29 09:00:01

objc系列译文(6.4):深入理解 CocoaPods的相关文章

iOS 7系列译文:认识 TextKit

OS 7:终于来了,TextKit.   功能 所以咱们到了.iOS7 带着 TextKit 登陆了.咱们看看它可以做什么!深入之前,我还想提一下,严格来说,这些事情中的大部分以前都可以做.如果你有大量的资源和时间来用CoreText构建一个文本引擎,这些都是可以做的.但是如果以前你想构建一个完善的富文本编辑器,你得花费几个月的时间.现在就非常简单,你只需要到在Xcode里打开一个界面文件,然后将UITextView拖到你的试图控制器,就可以获得所有的功能: 字距调整(Kerning):所有的字

Core Data系列译文:Core Data概述

在"伯乐在线"发现了一篇很不错的关于CoreData的文章,只是那里不能收藏,故而转载至此 以下是文章原文: 本文由 伯乐在线 - IvyShao 翻译自 Daniel Eggert.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. [2013-11-19 21:24:26 伯乐在线补充]:由于之前和译者@shaojingkk 沟通不够,我们在发布这篇译文之前并不知道译者参考对照@answer-huang 之前的译文版本,所以发布文章时未能在文中特别说明,责任在我们,在此向@answ

重学Golang系列(一): 深入理解 interface和reflect

前言 interface(即接口),是Go语言中一个重要的概念和知识点,而功能强大的reflect正是基于interface.本文即是对Go语言中的interface和reflect基础概念和用法的一次梳理,也算是我阶段学习的总结,以期温故而知新. interface(接口) 定义 在Go语言中,如果自定义类型(比如struct)实现了某个interface中的所有方法,那么就可以说这个类型实现了这个接口.接口可如下定义: type 接口名称 interface { method1(参数列表)

性能测试心得系列一:我所理解的性能测试

性能测试的概念,我就不说了,百度一下,会出来一大堆,每一种说法都有一定的道理.什么是性能测试呢? 请不要告诉我是测试一个测试对象的性能:),性能测试,就我目前了解到的来说,很多时候都是很难去定位的,有很多东东可能会绊住我们前进的步伐!现在我们大体讲下,我所理解的大致思路针对于一个要上线的新功能来说,怎么去做. 首先,我们如果有条件最好去做下 单用户下的自动化测试,去daily的check,新功能的性能表现怎样.实在不能自动化完成,也要手动的去完成. 1) 新功能设置成为一个事物,去结合httpw

深入理解 CocoaPods

本文由 伯乐在线 - programmer.du 翻译自 Michele Titolo.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. Cocoapods是 OS X 和 iOS 下的一个第三方库管理工具.你能使用CocoaPods添加被称作“Pods”的依赖库,并轻松管理它们的版本,而不用考虑当前的时间和开发环境. Cocoapods意义体现在两个方面.首先,引入第三方库无可避免地要进行各种各样的配置.对于Objective-C的初级开发者来说,项目配置可是一件艰巨的任务.在配置编译阶段和

深入理解CSS系列(一):理解CSS的盒子模型

接触前端也有好几个年头了,但是,讲实话,对于CSS的理解真的是不敢恭维,相信很多同行也有类似的感受吧!这是为什么呢?因为我们都认为CSS太简单了,没有必要深入学习,果真如此?其实,只不过是自己图样图森破罢了.如果真的那么简单,为什么经常会遇到一些奇怪的样式问题,而要折腾好长时间呢?就是因为无从下手,终究还是基础不扎实啊!最近打算深入的学习一下CSS,以便遇到问题时,才知道如何下手,从而迅速的对症下药."深入理解"只是相对于我个人而言的哈,如果有大神觉得不够深入,请不喜勿喷.这是深入理解

Redis工作系列之一 与 Memcached对比理解

     近期公司项目在使用Redis,这几年Redis很火,Redis也常常被当作Memcached的挑战者被提到桌面上来.关于Redis与Memcached的比较更是比比皆是.然而,Redis真的在功能.性能以及内存使用效率上都超越了Memcached吗? You should not care too much about performances. Redis is faster per core with small values, but memcached is able to u

程序员谈话系列——关于redis的一些理解(二)

一,redis的数据类型都有什么? String hash list set sortedset HyperLogLog Pub/Sub 二,缓存雪崩,击穿,传统. 雪崩:一些热点数据都会做缓存,一般会同时进行定时任务刷新.如果key的失效时间时,大量的用户请求涌入会直接落到数据库上,数据库一般会报一下警,但很有可能没有反应就直接挂了.当然重启数据库也会直接被流量打死.比如如果打挂的是一个用户服务的库,那么依赖这个库的接口都会报错,如果不做熔断的话会瞬间挂到一片. 做法: 1,为了避免缓存雪崩,

iOS技术博客(文摘)链接地址

  objc系列译文(5.1):认识 TextKit 手把手教你配置苹果APNS推送服务 如何使用iOS Addressbook UIApplication深入研究 GCD倒计时 那些不能错过的Xcode插件 iOS开发系列--音频播放.录音.视频播放.拍照.视频录制 Mantle 初步使用 CABasicAnimation animationWithKeyPath Types 插件管理Alcatraz