
1. Podfile(用户定义依赖)
-
作用:声明项目所需的第三方库及其版本规则(如
~> 5.0),指定依赖源(如 GitHub、私有仓库)。 - 位置:项目根目录,需手动创建。
示例:
platform :ios, '13.0'
target 'MyApp' do
pod 'Alamofire', '~> 5.0' # 版本范围
pod 'SnapKit', :git => 'https://github.com/SnapKit/SnapKit.git' # 直接引用 Git
end
2. Podfile.lock(版本锁定)
-
作用:记录当前安装的精确版本(如
Alamofire 5.6.0),确保团队协作或重新安装时版本一致。 -
位置:项目根目录,自动生成(执行
pod install后创建)。 -
特点:
- 禁止手动修改。
- 提交到版本控制(Git)以保证一致性。
示例:
PODS:
- Alamofire (5.6.0)
- SnapKit (5.6.0)
DEPENDENCIES:
- Alamofire (~> 5.0)
- SnapKit (from `https://github.com/SnapKit/SnapKit.git`)
SPEC REPOS:
trunk: Alamofire
https://github.com/SnapKit/SnapKit.git: SnapKit
CHECKSUMS: ... # 校验和确保完整性
Podfile.lock文件主要包含:PODS、DEPENDENCIES、SPEC REPOS、SPEC CHECKSUMS、PODFILE CHECKSUM,用来记录每个pod的版本号、依赖的其他库和每个库对应的podspec.json文件的checksum(SHA1的值)。
Podfile.lock 用于最后一次更新Pods时,记录所有第三方框架的版本号,通过它记录的这些信息可以确保多人协作时,大家在pod install时会首先使用Podfile.lock来下载安装相同版本的第三方库,保证依赖同步。
3. .podspec(库的元数据)
- 作用:描述单个库的元信息(名称、版本、源码地址、依赖等),用于发布到 CocoaPods 仓库。
- 位置:库的源代码仓库中,由库开发者维护。
podspec 文件是 CocoaPods 中用于描述和配置一个库(或者称为 Pod)的文件,当我们创建并封装一个基于CocoaPods的属于自己的三方库时,会伴随创建一个podspec 文件来定义这个库的元数据。
通过 pod install 命令 CocoaPods 将会依次读取每个依赖库根目录下的podspec文件并下载、安装相应的依赖库。
示例(Alamofire.podspec):
Pod::Spec.new do |s|
s.name = "Alamofire"
s.version = "5.6.0"
s.summary = "HTTP Networking Library"
s.homepage = "https://github.com/Alamofire/Alamofire"
s.license = { :type => "MIT" }
s.source = { :git => "https://github.com/Alamofire/Alamofire.git", :tag => s.version }
s.source_files = "Source/**/*.swift"
s.ios.deployment_target = "10.0"
s.dependency "SomeOtherLib", "~> 3.0" # 声明该库的依赖
end
4. Podfile、Podfile.lock 和 .podspec 之间的关系
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ │ │ │
│ .podspec │◄──────┤ Podfile ├──────►│ Podfile.lock │
│ (库的元数据)│ │ (用户需求) │ │ (版本锁) │
│ │ │ │ │ │
└──────┬──────┘ └───────┬──────┘ └───────┬──────┘
│ │ │
▼ ▼ ▼
┌───────────────────────────────────────────────────────────┐
│ CocoaPods 依赖解析流程 │
│ │
│ 1. 读取 Podfile 中的依赖声明 │
│ 2. 查找对应 .podspec 获取库信息(版本、源码地址等) │
│ 3. 解析依赖树并下载库 │
│ 4. 生成 Podfile.lock 锁定实际安装版本 │
└───────────────────────────────────────────────────────────┘
| 文件 | 谁创建 | 作用 | 是否提交 Git | 修改频率 |
|---|---|---|---|---|
Podfile |
开发者手动创建 | 声明项目依赖的库和版本规则 | ✅ 是 | 需要时更新 |
Podfile.lock |
CocoaPods 自动生成 | 锁定当前安装的精确版本 | ✅ 是 | 每次 pod install 后更新 |
.podspec |
库开发者创建 | 描述库本身的元数据(版本、源码等) | 在库的仓库中 | 发布新版本时更新 |
协作流程示例
-
开发者A:
- 在
Podfile添加pod 'Alamofire', '~> 5.0'。 - 运行
pod install:- CocoaPods 读取
.podspec找到最新兼容版本(如5.6.0)。 - 安装库并生成
Podfile.lock(记录Alamofire 5.6.0)。
- CocoaPods 读取
- 提交
Podfile和Podfile.lock到 Git。
- 在
-
开发者B:
- 拉取代码后运行
pod install。 - CocoaPods 读取
Podfile.lock,直接安装5.6.0(无视此时是否有新版本5.7.0)。
- 拉取代码后运行
-
升级依赖:
- 若需升级,开发者需:
- 修改
Podfile(如改为pod 'Alamofire', '~> 5.6')。 - 运行
pod update Alamofire更新库和Podfile.lock。
- 修改
- 若需升级,开发者需:
💡 关键规则:
- 修改
Podfile后 → 用pod install(根据Podfile.lock安装)。- 升级库版本 → 用
pod update [库名](更新Podfile.lock)。
Pod常用指令区别
pod install
- 如果
Podfile.lock文件不存在,会根据Podfile文件安装第三方框架,并生成Podfile.lock文件; - 如果
Podfile.lock文件存在,会根据Podfile.lock文件的版本号来安装第三方框架。
pod update
- 根据
Podfile文件安装第三方框架; -
将所有第三方框架更新到最新版本,并且创建一个
Podfile.lock文件覆盖掉原Podfile.lock 文件。
pod install / update --no-repo-update
安装框架前不会执行pod repo update,意味着不去检查服务器版本,直接使用本地缓存的框架版本:

pod install / pod update 过程:
- 在通过
pod install或pod update指令安装框架前,都会先执行pod repo update指令,将服务器最新的框架下载到本地,项目中是否安装最新版本的框架,取决于安装方式:pod install(指定版本)和pod update(最新版本);- 在第一次执行
pod install指令时,podfile.lock还不存在,会根据podfile中的说明来集成框架。如果指定了框架版本号,则安装指定版本,如果未指定,则安装最新的,并自动生成podfile.lock文件;- 当以后再次执行
pod install指令时,会根据podfile.lock中记录的框架版本号来安装框架;- 即便服务器中有最新的版本,通过
pod install指令也不会安装最新的第三方框架,只会根据podfile.lock中记录的版本来安装。
项目中的运用
-
Podfile.lock应该加入版本控制,保证组内小伙伴们的依赖库版本一致,防止出现难以发现的bug,在初始创建项目的时候就应该加入版本控制; - 理解
pod install和pod update的区别,及它们对Podfile.lock的影响,合理使用; -
Podfile的语法最好能尽量严谨,最好指定明确的依赖库版本。
Podfile更像是一个版本协议,而Podfile.lock才是项目中最后真正使用的版本。
如果让你去确定你app使用某一个三方库的版本,你不应该找Podfile,而是应该找Podfile.lock文件。
创建podspec
创建podspec文件只需要一行命令,在你自己的三方库的根目录下输入下面的命令:
pod spec create XXXModule
一个完整的podspec文件内容,如下:

podspec中常用的配置信息字段:
name:框架的名字
version:当前版本(注意,是当前版本,假如你后续更新了新版本,需要修改此处,以后打的tag,保持和versin)
summary:简要描述,在pod search ZCPKit的时候会显示该信息。
description:详细描述
homepage:页面链接
license:开源协议
author:作者
source:源码git地址
platform:支持最低iOS版本
source_files:源文件(可以包含.h和.m)
public_header_files:头文件(.h文件)
resources:资源文件(配置的文件都会被放到mainBundle中)
resource_bundles:资源文件(配置的文件会放到你自己指定的bundle中)
frameworks:依赖的系统框架
vendored_frameworks:依赖的非系统框架
libraries:依赖的系统库
vendored_libraries:依赖的非系统的静态库
dependency:依赖的三方库
podspec 的内容配置
/// source_files:配置三方库的源文件(.h或.m文件)
source_files = 'XhmModule/Classes/xhmKit.{h,m}' // 直接指定文件名
source_files = 'XhmModule/Classes/*.{h,m}' // Classes文件夹下的所有匹配文件
source_files = 'XhmModule/Classes/**/*.{h,m}' // Classes所有路径下的所有匹配文件
source_files = 'XhmModule/Classes/**/*' //表示匹配所有文件(主目录和子目录,其中**相当于省略中间层级)
source_files = 'XhmModule/Classes/*' //表示匹配所有classes目录下文件,不包含子目录的
source_files = 'XhmModule/Classes/NSURLSession/*.{h,m} ' //表示匹配NSURLSession所有以.h和.m结尾的文件
/// public_header_files:配置公有的头文件(.h文件)
public_header_files = 'XhmModule/Classes/xhmKit.{h,m}' // 直接指定文件名
public_header_files = 'XhmModule/Classes/*.h' // Classes文件夹下的所有匹配文件
public_header_files = 'XhmModule/Classes/**/*.h' // Classes所有路径下的所有匹配文件
/// vendored_frameworks:配置需要引用的非系统框架
vendored_frameworks = 'XhmModule/Frameworks/xhmFramework.framework'
/// frameworks:配置依赖的系统框架
frameworks = 'AVFoundation', 'CoreGraphics'
/// vendored_libraries:配置需要引用的非系统静态库
/// 要注意,这里的.a静态库名字必须要带lib前缀,如果引用的静态库名字没lib前缀会导致编译报错,只需要重命名加上即可
vendored_libraries = 'XhmModule/Frameworks/libXhmKit.a'
/// libraries:配置依赖的系统库(要注意,这里的写法需要忽略lib前缀)
libraries = 'c++', 'sqlite3', 'stdc++.6.0.9', 'z'
/// resources:配置资源文件(.bundle,.png,.txt等资源文件,这些资源文件会被放到mainBundle中,要注意避免发生命名重复的问题)
resources = 'Resources/MyRes.bundle'
/// resource_bundles:配置指定bundle的资源文件(可以解决resources导致的命名冲突问题)(推荐使用该方式配置资源)
spec.resource_bundles={
'MyLibrary'=>['Resources/*.png'],
'OtherResources'=>['OtherResources/*.png']
}
s.resource_bundles = {
'XhmModule' => ['XhmModule/Assets/*.png', 'XhmModule/Assets/pic/*.png']
}
/// dependency:依赖的三方库,pod库或者可以是自身的subspec
dependency 'AFNetworking', '~>4.0.0' // pod三方库
dependency 'XhmModule/Tools' // 自身的subspec 使用的是层级路径
dependency 'AFNetworking'
目录分层实现
目录分层的好处:
目录分层,结构清晰;
使用pod引入一个三方库时,可以只引入一个subspec而不用将整个三方库引入。
下面举列说明,如图所示目录结构:


写法如下:
Pod::Spec.new do |s|
s.name = 'XhmModule'
s.version = '0.1.0'
s.summary = '创建自定义的私有库'
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'https://gitee.com/xhm121'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'hou.xiahou' => 'min.xiahou@renren-inc.com' }
s.source = { :git => 'https://gitee.com/xhm121/hmprivate-pods.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '9.0'
s.source_files = 'XhmModule/Classes/*'
s.public_header_files = 'XhmModule/Classes/CommonHeader.h'
s.subspec 'Tools' do |ss|
ss.source_files = 'XhmModule/Classes/Tools/*'
s.dependency 'SDWebImage', '~> 5.12'
end
s.subspec 'Base64' do |ss|
ss.source_files = 'XhmModule/Classes/Base64/*'
end
s.subspec 'MD5' do |ss|
ss.source_files = 'XhmModule/Classes/MD5/*'
ss.dependency 'XhmModule/Tools'
end
s.resource_bundles = {
'XhmModule' => ['XhmModule/Assets/*.png', 'XhmModule/Assets/pic/*.png']
}
end
效果:

有几个需要注意的地方:
- 层级不能出现循环依赖
比如类Base64Additions.h中 #import "NSString+MD5.h",同时NSString+MD5.h中 #import "Base64Additions.h"。
这样当写podspec时就需要在Base64层级中写,dependency 'XhmModule/MD5',在MD5层级中写dependency 'XhmModule/Base64',如此便存在Base64与MD5层级之间的循环依赖。出现循环依赖时,三方库是无法成功提交到repo上的,会报依赖错误。
解决办法是,使用 public_header_files,创建CommonHeader文件在该文件中把相互引用的文件包含进去,例如
s.public_header_files = 'XhmModule/Classes/CommonHeader.h'
- 不同层级需要引用文件的时候,得添加依赖(排除相互依赖的情况下)
例如:MD5层级中的NSString+MD5.m引用了Tools层级中的文件,应该给MD5层级添加依赖,如下
s.subspec 'MD5' do |ss|
ss.source_files = 'XhmModule/Classes/MD5/*'
ss.dependency 'XhmModule/Tools'
end
- source_files使用的是真实的物理路径,而dependency依赖其他层级时使用的是层级路径,不是真实的物理路径。
例如:UIImage+MyLibrary.h文件的真实路径是:XhmModule/Classes/Tools,而Tools层级是属于XhmModule层级下的一个子subspec,所以当写MD5层级依赖Util层级时要写:dependency 'XhmModule/Tools'而不是dependency 'XhmModule/Classes/Tools'
如何校验podspec文件
在podspec写好之后我们需要验证一下编写的内容是否有误。可以在命令行的三方库当前路径下使用下面的命令:
pod lib lint (从本地验证你的pod能否通过验证)
pod spec lint (从本地和远程验证你的pod能否通过验证)
pod lib lint --verbose (加--verbose可以显示详细的检测过程,出错时会显示详细的错误信息)
pod lib lint --allow-warnings (允许警告,用来解决由于代码中存在警告导致不能通过校验的问题)
pod lib lint --help (查看所有可选参数,可选参数可以加多个)
// 跳转到XhmModule.podspec 目录下去执行
pod repo push XhmModule XhmModule.podspec --allow-warnings
podspec验证相关参数的作用:
--allow-warnings : 忽略警告,即可以允许有警告也可以通过验证
--use-libraries: 使用静态库安装规范,当包含依赖的第三方或自定义的静态库需要添加此规范
--use-modular-headers: 如果是OC和swift 的混编需要加上
--sources=https://cdn.cocoapods.org/: 指定索引库的源,多个源必须用逗号分隔
--local-only: 不执行将回购推到其远程服务器的步骤
--no-private: 包括仅适用于公共回购的检查
--skip-import-validation: 跳过验证pod是否可以导入
--skip-tests: 在验证期间跳过构建和运行测试
--commit-message="Fix bug in pod": 添加自定义提交消息。如果没有指定提交消息,则打开默认编辑器
--use-json: 在将其推送到repo之前,将podspec转换为JSON
--swift-version=VERSION: 在标记规范时应该使用的SWIFT_VERSION。这优先于规范中指定的Swift版本或. Swift版本文件
--no-overwrite: 不允许将覆盖现有规范的推送
iOS组件化之pod加载资源文件 iOS项目组件化遇到的问题及解决(100%遇得到) podspec官方网站
Podspec语法参考 v1.2.0.beta.1 podspec 校验报错问题指南
组件化之podspec文件
//www.greatytc.com/p/58979216ed4f
