CocoaPods将所有的依赖库都放到Pods项目中,让主项目依赖Pods项目,这样源码管理工作都从主项目迁移到了Pods项目中
- Pods项目最终会编译成一个名为libPods.a文件,主项目只需要依赖这个.a文件即可(也有可能是.framework文件)
- 对于资源文件,CocoaPods提供了一个名为Pods-resources.sh的bash脚本,该脚本在每次编译的时候都会执行,将第三方库的各种资源文件复制到目标目录中
- CocoaPods通过一个名为Pods.xcodeproj的文件来在编译时设置所有的依赖和参数
核心组件
CocoaPods是用 Ruby 写的,并由若干个 Ruby 包 (gems) 构成的。在解析整合过程中,最重要的几个 gems 分别是: CocoaPods/CocoaPods, CocoaPods/Core, 和 CocoaPods/Xcodeproj (是的,CocoaPods 是一个依赖管理工具 -- 利用依赖管理进行构建的!)。CocoaPods 是一个 objc 的依赖管理工具,而其本身是利用 ruby 的依赖管理 gem 进行构建的.
CocoaPods/CocoaPod
这是一个面向用户的组件,每当执行一个pod命令时,这个组件都将被激活。该组件包括了所有使用CocoaPods涉及的功能,并且还能通过调用所有其他的gems来执行任务
CocoaPods/Core
Core组件提供支持与CocoaPods相关文件的处理,文件主要是Podfile和podspecs
Podfile
Podfile 是一个文件,用于定义项目所需要使用的第三方库.
Podspec
.podspec 也是一个文件,该文件描述了一个库是怎样被添加到工程中的。它支持的功能有:列出源文件、framework、编译选项和某个库所需要的依赖等.
CocoaPods/Xcodeproj
这个 gem 组件负责所有工程文件的整合。它能够对创建并修改 .xcodeproj 和 .xcworkspace 文件。它也可以作为单独的一个 gem 包使用。如果你想要写一个脚本来方便的修改工程文件,那么可以使用这个 gem
首先我们cd到~/.cocoapods/repos/master/Specs
路径下,选择其中一个第三方库,查看其AFNetwork.podspec.json
文件(以AFNetwork为例):
{ "name": "AFNetwork", "version": "0.1.0", "summary": "Simple request manager about AFNetworking", "description": "TODO: Add long description of the pod here.", "homepage": "https://github.com/lingyfh/AFNetwork", "license": { "type": "MIT", "file": "LICENSE" }, "authors": { "lingyfh": "LingYFH@gmail.com" }, "source": { "git": "https://github.com/lingyfh/AFNetwork.git", "tag": "0.1.0" }, "platforms": { "ios": "8.0" }, "public_header_files": [ "AFNetwork/*.h", "AFNetwork/**/*.h" ], "source_files": "AFNetwork/Classes/**/*", "dependencies": { "AFNetworking": [ "~> 3.0" ] } }
可以看到这里包含了所有三方看的信息,包括名字、协议、描述、Github地址、支持平台等
pod install的过程
通常我们在Podfile文件中新增引入第三方库的代码后,执行pod install, 对应的第三方库就安装在Pods项目中了,pod install 这一过程发生了什么呢,我们这个命令后边加上 --verbose, 可以看到如下内容:
xxx@xxxdeMacBook-Pro CocoaPodsDemo % pod install --verbose Preparing Analyzing dependencies Inspecting targets to integrate Using `ARCHS` setting to build architectures of target `Pods-defaults-CocoaPodsDemo `: (``) Finding Podfile changes - AFNetworking Resolving dependencies of `Podfile` CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only perfomed in repo update Comparing resolved specification to the sandbox manifest - AFNetworking Downloading dependencies -> Using AFNetworking (3.2.1) - Running pre install hooks Generating Pods project - Creating Pods project - Installing files into Pods project - Adding source files - Adding frameworks - Adding libraries - Adding resources - Linking headers - Installing Pod Targets - Installing target `AFNetworking` iOS 7.0 - Generating dummy source at `Pods/Target Support Files/AFNetworking/AFNetworking-dummy.m` - Generating deterministic UUIDs - Stabilizing target UUIDs - Running post install hooks - Podfile - Writing Xcode project file to `Pods/Pods.xcodeproj` Cleaning up sandbox directory Integrating client project Integrating target `Pods-defaults-CocoaPodsDemo ` (`CocoaPodsDemo.xcodeproj` project) - Running post integrate hooks - Writing Lockfile in `Podfile.lock` - Writing Manifest in `Pods/Manifest.lock` CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only perfomed in repo update -> Pod installation complete! There are 1 dependencies from the Podfile and 1 total pods installed.
分析过程:
- 读取Podfile文件,分析有哪些第三方依赖库及对应的版本
- 加载源文件,每个
xxx.podspec.json
文件都包含一个源代码的索引,这些索引包含一个Git地址和Git tag,它们以commit SHAs的方式存在在~/Library/Caches/CocoaPods
中,这个路径中文件的创建是由Core gem负责的,CocoaPods将依照Podfile、.podspec和缓存文件的信息将源文件下载到pods目录中 - 生成
Pods.xcodeproj
,每次pod install指向,如果检测到改动时,CocoaPods会利用Xcodeproj gem组件对Pods.xcodeproj
进行更新,该文件如果不存在,则用默认配置生成,否则会将已有的配置项加载至内存中 - 安装第三方库,当CocoaPods往工程中添加一个三方库时,不只是添加代码这么简单,还会添加很多内容,由于每个第三方库有不同的Target,因此对于每个库,都会有几个文件需要添加,每个target都需要:
- 一个包含编译选项的.xcconfig文件
- 一个同时包含编译设置和CocoaPods默认配置的私有.xcconfig文件
- 一个编译所必须的prefix.pch文件
- 另一个编译必须的文件dummy.m
以AFNetworking为例:
一旦每个pod的target完成了上面的内容,整个Pod target就会被创建,这增加了相同文件的同时,还增加了另外几个文件,如果源码中包含有资源bundle,将这个bundle添加至target的指令将被添加到Pod-Resources.sh文件中。还有一个名为Pods-environment.h的文件,文件中包含了一些宏,这些宏可以用来检查某个组件是否来自pod,最后生成两个认可文件,一个是plist, 另一个是markdown,这两个文件用于给最终用户查阅相关许可信息
- 写入磁盘,直到现在,许多工作都是在内存中进行的。为了让这些成果能被重复利用,我们需要将所有的结果保存到一个文件夹中,所以Pods.xcodeproj文件被写入磁盘,另外两个非常重要的文件:Podfile.lock和Manifest.lock都将被写入磁盘
- Podfile.lock,这是CocoaPods创建的最重要的文件之一,它记录了需要被安装的pod的每个已安装的版本。如果你想知道已安装的pod是哪个版本,可以查看这个文件,推荐将Podfile.lock文件加入打版本控制中,这有助于整个团队的一致性
- Mainfest.loc 这是每次运行pod install命令时创建的Podfile.lock文件的副本,如果你遇到过这样的错误:沙盒文件与Podfile.lock文件不同步(
The sandbox is not in sync with the Podfile.lock
), 这是因为Manifest.lock文件和Podfile.lock文件不一致所引起。由于Pods所在的目录并不总在版本控制之下,这样可以保证开发者运行app之前都能更新他们的pods,否则app可能会crash,或者在一些地方编译失败 - xcproj,如果你已经安装我们的建议在系统上安装了xcproj,它会对Pods.xcodeproj文件执行一下touch以将其转换成为旧的ASCII plist格式的文件.为什么要这么做呢?虽然在很久以前就不被其他软件支持了,但是xcode仍然依赖于这种格式。如果没有xcproj,你的Pods.xcodeproj文件将会以XML格式的plist文件存储,当你用Xcode打开它时,它会被改写,并造成大量的文件改动