iOS CocoaPods私有库完整搭建+踩坑实战总结

306 阅读15分钟

iOS 私有库创建与推送远程——问题排查总结文档

场景:使用 CocoaPods 创建 iOS 私有库并推送到 Gitee 远程仓库,过程中遇到的一系列报错与解决记录。 适用对象:iOS 开发者 / CocoaPods 私有组件维护者。


一、核心概念(必须分清两个仓库)

仓库作用内容使用命令
源码仓库 my-private-sdk存放组件代码Classes/ 源码、.podspec、git taggit remote add / git push / git tag
Spec 索引仓库 my-private-specs存放 podspec 描述索引各版本 0.1.0/xxx.podspec(不放源码)pod repo add / pod repo push

⚠️ 两个仓库必须分开、独立,绝对不能混用地址,这是整套方案最容易出错的地方。

关键理解:一个 Spec 仓库可管理多个私有组件

  • 源码仓库:每新增一个私有库,就要新建一个独立的源码仓库(组件代码互相独立)
  • Spec 索引仓库:全局只维护 1 个,所有内部组件的 podspec 都集中放这里,一次创建、长期复用
  • 所以新增第二个、第三个私有库时,不需要新建 Spec 仓库,复用已有的 MyPrivateSpecs 即可

二、完整正确步骤(标准私有库方案·创建第一个库)

0. 前置

  • 本地安装 CocoaPods:gem install cocoapods,验证 pod --version
  • Gitee 网页新建两个空仓库:
    1. my-private-sdk(源码仓库)
    2. my-private-specs(Spec 索引仓库)
  • ⚠️ 创建时不要勾选 README、.gitignore、license,必须是纯空仓库

1. 创建本地私有库模板

pod lib create MyPrivateSDK
# 交互选择:iOS / ObjC或Swift / 带Demo / 测试框架None
cd MyPrivateSDK
  • 代码放入 MyPrivateSDK/Classes/(不是 Example)

2. 修改 podspec

  • 重点:s.version、s.source(指向源码仓库 git 地址 + tag)
  • s.version 必须与后面 git tag 完全一致

3. 推送源码仓库并打 tag

git add .
git commit -m "init v0.1.0"
git remote add origin https://gitee.com/<user>/my-private-sdk.git
git push -u origin main
git tag 0.1.0
git push origin 0.1.0

4. 添加 Spec 仓库

pod repo add MyPrivateSpecs https://gitee.com/<user>/my-private-specs.git
pod repo list

5. 校验 podspec

pod lib lint MyPrivateSDK.podspec --allow-warnings
# 必须看到 passed validation

6. 推送 podspec 到 Spec 远端

pod repo push MyPrivateSpecs MyPrivateSDK.podspec --allow-warnings

7. 使用方 Podfile

source 'https://gitee.com/<user>/my-private-specs.git'
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '12.0'
target 'TestApp' do
  pod 'MyPrivateSDK', '~> 0.1.0'
end
pod install

8. 迭代发版流程

改代码 → 改 s.version='0.2.0' → commit → git tag 0.2.0 && git push origin 0.2.0 → pod lib lint → pod repo push


三、新增第二个私有库完整步骤(复用同一个 Spec 仓库)

前提:MyPrivateSpecs 已配置好(远端仓库有 main 分支、本地 pod repo add 已成功) ✅ 核心:不需要新建第二个 Spec 仓库,也不要再次执行 pod repo add,只新建新组件的源码仓库

1. Gitee 网页新建【第二个组件源码仓库】

仓库名例如:MyImageLoaderSDK

  • 类型:私有
  • ❌ 不要勾选 README、gitignore、license,创建纯空仓库

2. 本地创建 pod 库模板

pod lib create MyImageLoaderSDK
cd MyImageLoaderSDK
  • 交互选项与之前一致(iOS、语言、带 Demo、测试框架 None)
  • 源码放入 MyImageLoaderSDK/Classes

3. 修改 MyImageLoaderSDK.podspec

Pod::Spec.new do |s|
  s.name             = 'MyImageLoaderSDK'
  s.version          = '0.1.0'
  s.summary          = '图片加载私有组件'
  s.description      = <<-DESC
图片加载内部私有SDK
                       DESC
  s.homepage         = 'https://gitee.com/<user>/my-image-loader-sdk'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'xxx' => 'xxx@xx.com' }
  s.source           = { :git => 'https://gitee.com/<user>/my-image-loader-sdk.git', :tag => s.version.to_s }

  s.ios.deployment_target = '12.0'
  s.source_files = 'MyImageLoaderSDK/Classes/**/*'
end

s.name 必须与库名一致,s.version 初始 0.1.0

4. 源码推送到【新组件源码远端】并打 tag

git add .
git commit -m "init MyImageLoaderSDK v0.1.0"
git remote add origin https://gitee.com/<user>/my-image-loader-sdk.git
git push -u origin main

git tag 0.1.0
git push origin 0.1.0

5. 校验 podspec(必须)

pod lib lint MyImageLoaderSDK.podspec --allow-warnings
# 看到 passed validation 再往下

6. push podspec 到同一个私有 Spec 仓库 MyPrivateSpecs

✅ 重点:仍用之前的 MyPrivateSpecs,不要新建 spec 仓库

pod repo push MyPrivateSpecs MyImageLoaderSDK.podspec --allow-warnings

成功后远端 my-private-specs 自动新增目录:

MyImageLoaderSDK/
└── 0.1.0/
    └── MyImageLoaderSDK.podspec

现在该 Spec 仓库同时管理:MyPrivateSDK、MyImageLoaderSDK。

7. 项目 Podfile 同时引入多个私有库

# 共用同一个私有 spec 源
source 'https://gitee.com/<user>/my-private-specs.git'
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '12.0'
target 'DemoApp' do
  pod 'MyPrivateSDK', '~>0.1.0'
  pod 'MyImageLoaderSDK', '~>0.1.0'
end
pod install

8. 其他同事电脑使用

只需执行一次即可拉取所有私有组件:

pod repo add MyPrivateSpecs https://gitee.com/<user>/my-private-specs.git

四、对话中遇到的具体问题与解决

问题 1:git remote add origin 之后 push 失败(远端仓库没建)

现象:push 报 Repository not found 原因:git remote add origin xxx.git 只是本地记录地址,远端仓库必须先建好。 解决:

  1. Gitee 网页先新建空仓库(不勾选任何初始化选项)
  2. 复制仓库 HTTPS/SSH 地址
  3. 再执行 git remote add origin <地址> + git push

勾选了 README 会导致 refusing to merge unrelated histories 冲突,所以建仓必须纯空。

问题 2:没执行 pod repo add 也能 pod install 成功

原因:使用了另一种简易写法,完全绕过了 Spec 索引仓库:

# 简易写法:直接指向源码仓库 + tag,不需要 pod repo add
pod 'MyPrivateSDK', :git => 'https://gitee.com/<user>/my-private-sdk.git', :tag => '0.1.0'

对比:

写法机制是否需 spec 仓库
:git => ... , :tag => ...直接拉源码仓库对应 tag,绕过索引❌ 不需要
'MyPrivateSDK', '~>0.1.0'走 Spec 索引查找 → 按 spec 里的 source 拉源码✅ 必须 pod repo add

pod repo add 不执行也能拉取 = 你用的是 :git/:tag 简易方案。多组件、需版本约束 ~>、pod search、团队协作时才需升级到标准 Spec 方案。

问题 3:git repo MyPrivateSpecs xxx.git 报 unknown subcommand

原因:把 CocoaPods 命令误当成了 git 命令。 解决:命令是 pod repo,不是 git repo。git 本身没有 repo 子命令。

问题 4:pod repo MyPrivateSpecs xxx.git 报 Unknown command

原因:pod repo 后面缺少子命令 add。 解决:

pod repo add MyPrivateSpecs <spec仓库git地址>
# 语法:pod repo add <本地别名> <远端spec仓库url>

问题 5:An unexpected version directory 'Classes' was encountered 报错

现象:push 后本地 Spec 仓库目录出现 Classes 文件夹。 原因:Spec 仓库目录结构被破坏。正确结构只允许版本号目录:

MyPrivateSpecs/
└── MyPrivateSDK/
    └── 0.1.0/
        └── MyPrivateSDK.podspec   # ✅ 正确

解决:

  1. pod repo remove MyPrivateSpecs 删掉本地坏仓库
  2. 清空 Gitee 远端 my-private-specs 残留文件
  3. 重新 pod repo add(地址必须用 my-private-specs.git)
  4. cd MyPrivateSDK → pod lib lint → pod repo push

记住:Spec 仓库只存 podspec,绝不放 Classes 源码,源码在 my-private-sdk 仓库。

问题 6:Your configuration specifies to merge with the ref 'refs/heads/master' ... but no such ref was fetched

现象:pod repo add 后 pull 报找不到 master 分支。 原因:Gitee 远端 my-private-specs 是空仓库,没有任何分支(main/master 都不存在)。 解决(先给 Spec 远端初始化一个主分支):

# 1 删本地
pod repo remove MyPrivateSpecs

# 2 临时目录初始化并推送 main 分支到远端
mkdir tmpSpecRepo && cd tmpSpecRepo
git init
touch README.md
git add README.md && git commit -m "init spec repo main branch"
git remote add origin https://gitee.com/<user>/my-private-specs.git
git push -u origin main

# 3 Gitee 网页将默认分支设为 main
# 4 重新添加
pod repo add MyPrivateSpecs https://gitee.com/<user>/my-private-specs.git

# 5 回 SDK 目录
cd ../MyPrivateSDK
pod lib lint MyPrivateSDK.podspec --allow-warnings
pod repo push MyPrivateSpecs MyPrivateSDK.podspec --allow-warnings

main / master 都支持,关键是远端仓库至少有一个分支。临时目录用完可删。


五、命令速查表

操作命令
新建库模板pod lib create <SDK名>
校验 podspecpod lib lint <SDK>.podspec --allow-warnings
查看本地 spec 仓库pod repo list
添加 spec 仓库pod repo add <别名> <spec仓库url>
推送 podspecpod repo push <别名> <podspec> --allow-warnings
删除本地 spec 仓库pod repo remove <别名>
查看远端分支git ls-remote https://gitee.com/<user>/my-private-specs.git

六、高频坑点总结

  1. 两仓库地址混用 → Spec 仓库地址填成源码仓库,导致目录错乱/Classes 报错。
  2. 建仓勾选 README → 本地 push 时 unrelated histories 冲突;Spec 仓库空无分支 → master 找不到。
  3. 命令写错 → 是 pod repo add,不是 git repo,不是 pod repo MyPrivateSpecs。
  4. 版本不一致 → s.version 与 git tag 必须严格一致,否则拉取失败。
  5. 路径大小写 → macOS 大小写敏感,s.source_files 路径写错会 lint 失败。
  6. 内网私有仓库 → 建议用 SSH 地址 git@gitee.com:<user>/xxx.git,提前配置 SSH 免密。
  7. pod repo push 失败排查顺序 → spec 语法 → 远端 spec 仓库权限 → tag 是否存在 → 分支是否存在。

新增私有库专项坑点

操作是否需要新建远端 Git 仓库
新增一个私有组件(新 SDK)✅ 新建源码仓库
新增一个私有组件❌ 不用新建 Spec 仓库,复用 MyPrivateSpecs
组件升级版本❌ 不用新建任何仓库,只需打新 tag + push spec
新增组件时执行 pod repo add❌ 不需要,本地已存在 MyPrivateSpecs

⚠️ 多个组件不能共用一个源码仓库,每个组件源码仓库必须独立。


七、快速判断用哪种方案

  • 临时 / 个人 / 单组件 → :git => ... , :tag => ...(无需维护 Spec 仓库)
  • 多组件 / 版本约束 / 团队协作 / pod search → 标准 Spec 仓库方案(需 pod repo add + pod repo push)

八、pod lib lint 常见警告与修复

关键认知:警告 ≠ 编译错误。pod lib lint 默认规则是「存在警告即判定校验失败」,加 --allow-warnings 可放行警告完成校验。正式组件建议修复核心警告,避免长期依赖 --allow-warnings。

警告 1:summary: The summary is not meaningful.

  • 原因:s.summary 描述过于简单(如只写"工具库")。
  • 修复:填写一句简短清晰的组件功能介绍。
s.summary = "iOS 项目通用工具集合,提供字符串、日期、UI相关工具方法"

警告 2:description: The description is shorter than the summary.

  • 原因:s.description 详细描述文本比摘要还短,不符合规范。
  • 修复:description 内容长度必须大于 summary。
s.description = <<-DESC
iOS 项目通用工具集合,封装常用字符串处理、日期转换、设备信息、UI辅助等工具方法,内部项目使用。
DESC

警告 3:problem validating the URL(homepage 不可访问)

  • 原因:CocoaPods 校验器无法访问 s.homepage 地址;私有仓库最容易出现(外网访问不了私有主页/地址写错/仓库不存在)。
  • 处理:
    • 公开库:核对并保证地址可访问
    • 私有内部库:该警告基本无法消除,可忽略,用 --allow-warnings 放行

警告 4:[iOS] swift: The validator used Swift 4.0 by default because no Swift version was specified.

  • 原因:podspec 未声明 Swift 版本,lint 默认按 Swift 4.0 校验。
  • 修复:在 podspec 添加 s.swift_versions(OC 库也可加上,不影响 OC 代码)。
s.swift_versions = ['5.0']

修复后的 podspec 片段(综合示例)

Pod::Spec.new do |s|
  s.name             = 'MyProjectTool'
  s.version          = '1.1.0'
  s.summary          = 'iOS 项目通用工具集合,提供字符串、日期、UI相关工具方法'
  s.description      = <<-DESC
iOS 项目通用工具集合,封装常用字符串处理、日期转换、设备信息、UI辅助等工具方法,内部项目使用。
DESC
  s.homepage         = 'https://github.com/yourname/MyProjectTool'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'yourname' => 'xxx@xx.com' }
  s.source           = { :git => 'https://github.com/yourname/MyProjectTool.git', :tag => s.version.to_s }

  s.ios.deployment_target = '12.0'
  s.source_files = 'MyProjectTool/Classes/**/*'
  s.swift_versions = ['5.0'] # 新增,修复 Swift 版本警告
end

校验命令

# 修复 podspec 后优先尝试不带 --allow-warnings
pod lib lint MyProjectTool.podspec

# homepage 链接警告依然存在(私有仓库场景)时使用
pod lib lint MyProjectTool.podspec --allow-warnings
# 看到 passed validation 即为通过

九、pod repo push 命令报错排查

报错:[!] A spec-repo name or url is required.

  • 原因:pod repo push 命令语法不全,缺少「spec 仓库别名」和「podspec 文件」两个必填参数。
  • 正确语法:
pod repo push 【spec仓库别名】【podspec文件】 --allow-warnings
  • 示例:
# 错误(不带参数,会报 required 错误)
pod repo push

# 正确
pod repo push MyPrivateSpecs MyProjectTool.podspec --allow-warnings
  • 查看本地 spec 仓库别名:
pod repo list
# 第一列就是别名,填入 push 命令

关键前置:版本号必须与源码 tag 严格一致

push 的 s.version(如 1.1.0)对应的源码仓库必须打好同名 tag 并推送到远端,否则 pod install 拉不到代码:

git tag 1.1.0
git push origin 1.1.0

appintentsmetadataprocessor 相关日志只是 Xcode 编译 note,完全不用处理。


十、私有 Spec 仓库发布进阶报错与命令规范(团队已有 Spec 仓库场景)

本章适用于:公司内网已有一套私有 Spec 仓库(本地别名如 MyPrivateSpecs,具体以 pod repo list 结果为准),团队新增组件、打 tag 后发布时遇到的高频问题。

进阶问题 1:pod repo push 报 Unable to find the 'xxx' repo

  • 现象:
pod repo push Specs XXX.podspec --allow-warnings
# [!] Unable to find the `Specs` repo. If it has not yet been cloned, add it via `pod repo add`.
  • 原因:pod repo push 的第一个参数必须是本地 Spec 仓库别名(pod repo list 第一列),不是远端 Git 仓库名。填了远端仓库名/远端地址都会找不到。
  • 解决:
pod repo list
# 第一列就是本地别名,替换命令里的参数
pod repo push MyPrivateSpecs XXX.podspec --allow-warnings
  • 要点:
    • 本地别名与远端仓库名可以不一致,pod repo add <本地别名> <远端地址> 时别名可自定;
    • 同一内网仓库可能被加了 ssh / http 两个别名,选一个统一使用,避免后面重复 spec 警告。

进阶问题 2:pod lib lint 报 Unable to find a specification for 'XXX' depended upon by ...

  • 现象:
ERROR | [iOS] unknown: Unable to find a specification for `MYDeviceLinkCore (~> 1.3.2)` depended upon by `MYDeviceInfoService`
  • 原因:pod lib lint / pod repo push 默认只在官方源(trunk/CDN)查找依赖,找不到你的内网私有依赖。
  • 解决:lint / push 时通过 --sources 显式指定私有源 + 官方源(逗号后不能有空格):
pod lib lint --sources=MyPrivateSpecs,trunk --allow-warnings --verbose
  • 补充:
    • MyPrivateSpecs 是本地私有 spec 仓库别名(pod repo list 查看),trunk 是官方源;
    • 确保私有 spec 仓库里已 push 过对应依赖的正确版本;
    • 本地 spec 太久没更新先 pod repo update MyPrivateSpecs。

进阶问题 3:ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code(M 芯片 Mac 高频)

  • 现象:只有 xcodebuild 返回非 0 错误码,日志只能看到依赖构建图,无直观编译报错,有时伴随 The Xcode build system has crashed。
  • 常见根因:
    1. --sources 别名写错/没写私有源,找不到团队私有依赖 → 依赖解析失败 → 构建失败;
    2. M 系列芯片模拟器架构冲突:老私有底层库不支持 arm64 模拟器架构,M 芯片编译模拟器架构直接报错(日志常见 all architectures in VALID_ARCHS are also in EXCLUDED_ARCHS);
    3. podspec 配置缺陷:source_files 路径写错、依赖版本不匹配、tag 与 s.version 不一致。
  • 解决步骤:
    1. pod repo list 确认别名,--sources 用正确别名;
    2. podspec 增加架构排除配置(优先只用 pod_target_xcconfig,避免 user_target_xcconfig 污染宿主工程):
s.pod_target_xcconfig = {
  'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64'
}
  1. 带 --verbose 查看完整编译日志定位真实报错;
  2. 指定 --platform=ios 只编译真机架构绕开模拟器;
  3. 应急调试 spec 语法可用 --skip-xcode-validation(只校验 spec,不编译代码,禁止作为上线依据)。

进阶问题 4:pod repo push 使用 --no-lint 跳过校验的规范

  • 常见高频用法(本地已完整 lint 通过、只想快速入库时):
pod repo push MyPrivateSpecs XXX.podspec --allow-warnings --no-lint
  • --no-lint 含义:推送阶段跳过内置 lint 校验,直接把 podspec 提交推送。
  • 优点:速度快,适合迭代发版、本地已充分验证过的场景。
  • ⚠️ 风险:
    • 不会校验 spec 语法、依赖是否存在、tag 是否存在、源码能否编译,错误 spec 也能入库;
    • 问题会延迟到业务工程 pod install 才暴露,排错成本更高;
    • 新人/首次发布不推荐,仅作熟手本地验证后的快速捷径。
  • ✅ 强制配套流程:
# 前置必须完整编译校验通过
pod lib lint --sources=MyPrivateSpecs,trunk --allow-warnings --verbose --platform=ios
# 校验 OK 后再快速推送
pod repo push MyPrivateSpecs XXX.podspec --allow-warnings --no-lint

进阶问题 5:大量 Found multiple specifications for 'XXX' 警告

  • 现象:pod lib lint 输出海量 [!] Found multiple specifications for 'XXX'。
  • 原因:本地同时存在两个 Spec 仓库副本指向同一个内网仓库(如一个 ssh 别名、一个 http 别名),或同时存在官方 git 源 + CDN 源,CocoaPods 找到多份相同 spec。
  • 解决:
    • 删除多余副本,保留一个私有源 + 一个官方源:
pod repo remove <多余别名>
pod repo list
  • Podfile 里 source 也不要同时写同一个私有仓库的 ssh + http 两个地址,统一保留一个。

发布命令速查(团队已有 Spec 仓库场景)

# 1 更新本地私有 spec 仓库
pod repo update MyPrivateSpecs

# 2 快速语法校验
pod lib lint --sources=MyPrivateSpecs,trunk --allow-warnings --quick

# 3 完整编译校验(上线前必须通过)
pod lib lint --sources=MyPrivateSpecs,trunk --allow-warnings --verbose --platform=ios

# 4 稳妥推送(自动 lint)
pod repo push MyPrivateSpecs XXX.podspec --sources=MyPrivateSpecs,trunk --allow-warnings --platform=ios

# 5 熟手快速推送(本地已 lint 通过再用)
pod repo push MyPrivateSpecs XXX.podspec --allow-warnings --no-lint

附录:CocoaPods 私有库高频命令速查清单

把 TeamPrivateSpec 替换为你本地 pod repo list 查到的私有源别名;xxx.podspec 替换为当前组件的 spec 文件名。

1. pod repo 私有索引仓库管理

# 查看本地所有spec仓库别名(排错首选)
pod repo list

# 添加私有Spec仓库(首次环境配置)
pod repo add TeamPrivateSpec git@xxx:iOS/Specs.git

# 更新本地私有索引(多人协作必执行)
pod repo update TeamPrivateSpec

# 删除异常仓库别名
pod repo remove TeamPrivateSpec

# 稳妥推送(自带lint校验,新版本首发)
pod repo push TeamPrivateSpec xxx.podspec --sources=TeamPrivateSpec,trunk --allow-warnings --platform=ios

# 熟手快速推送(跳过推送阶段校验)
pod repo push TeamPrivateSpec xxx.podspec --allow-warnings --no-lint

⚠️ 强制约束:使用 --no-lint 前,必须本地完整跑通 pod lib lint,避免脏 spec 入库。

2. pod lib lint 发布前校验(核心必跑)

# 轻量预检:只校验spec语法,不编译源码(速度快)
pod lib lint --sources=TeamPrivateSpec,trunk --allow-warnings --quick

# 完整编译校验(上线必须全部通过,输出详细日志)
pod lib lint --sources=TeamPrivateSpec,trunk --allow-warnings --verbose --platform=ios

# 仅校验spec结构,跳过Xcode编译(仅调试spec格式,不可用于发版)
pod lib lint --sources=TeamPrivateSpec,trunk --allow-warnings --skip-xcode-validation

参数说明

  • --sources=私有源,trunk:指定依赖搜索源,私有库必填,顺序不能颠倒
  • --allow-warnings:放行警告,不会阻断错误
  • --verbose:打印完整编译日志,排查 xcodebuild 报错神器
  • --platform=ios:只编译 iOS 平台,排除多余平台编译
  • --quick:轻量校验,不构建工程
  • --no-lint:push 时跳过内置 lint 检查

3. 配套辅助命令

# 查看CocoaPods版本
pod --version

# 清理缓存(依赖拉取异常时使用)
pod cache clean --all

# 组件Demo工程更新依赖
pod install
pod update

# 发版配套:打Git版本标签
git tag 1.0.0
git push origin 1.0.0

4. 标准发布流水线(固定执行顺序)

# 1. 更新本地私有索引
pod repo update TeamPrivateSpec

# 2. 快速语法预检
pod lib lint --sources=TeamPrivateSpec,trunk --allow-warnings --quick

# 3. 完整编译校验(必须全通过)
pod lib lint --sources=TeamPrivateSpec,trunk --allow-warnings --verbose --platform=ios

# 4. 推送至私有Spec仓库(日常快速版)
pod repo push TeamPrivateSpec xxx.podspec --allow-warnings --no-lint

5. 参数速查表

参数作用使用场景
--sources=A,trunk指定依赖源私有库必加
--allow-warnings允许警告日常调试、发布
--verbose输出详细日志排查编译报错
--platform=ios限定iOS平台减少无效编译
--quick轻量校验初步检查spec格式
--no-lint跳过push自带校验本地已跑完lint后的快速发布