我受够了 Xcode 的 SPM 网络问题,写了个脚本一劳永逸

上周五下午,项目 SPM 又卡在 Resolve 上了。进度条纹丝不动,等了 20 分钟,还是那个转圈。

我做了和每次一样的操作:开全局代理 → Resolve 成功 → 发现内网 GitLab 拉不到了 → 关代理 → 下次又卡。

这个循环我重复了大半年。终于决定彻底解决它。

问题出在哪

三个坑叠在一起:

1. Xcode 不走系统代理

终端里 git clone 飞快,Xcode 里 Resolve Package 卡死。原因是 Xcode 有自己的网络栈,不读系统的 http_proxy 设置,也不走 VPN 分流规则。

2. 全局代理和内网冲突

为了让 Xcode 能访问 GitHub,你开了全局代理。然后公司内网的 GitLab、Jenkins、各种内部服务全挂了。你要么来回切,要么配复杂的分流规则。

3. Reset Package 就从头来

好不容易下载完了,手一抖点了 Reset Package Caches(或者 Xcode 自己抽风),所有依赖重新下载。你前面等的 20 分钟白等了。

解题思路

我回想了 CocoaPods 时代的做法:pod install 在终端跑,终端天然支持代理配置。下完的库就在 Pods/ 目录里,Xcode 直接引用本地文件,根本不需要网络。

SPM 能不能也这么干?

能。Xcode 的 Add Local Package 功能,就是引用一个本地目录作为 SPM 包。那我只需要:

  1. 在终端把三方库 clone 下来(终端可以走代理)
  2. Xcode 引用本地路径(不走网络)

这样 Xcode 永远不需要自己去 GitHub 拉代码。Reset Package 也无所谓,本地文件还在。

实现

整个方案就三个文件:

bash 复制代码
 Packages/
 ├── packages.json             # 依赖清单
 ├── scripts/
 │   └── fetch-packages.sh     # 下载脚本
 └── Caches/                   # 三方库源码(gitignore)

依赖清单

packages.json 格式很简单,贴近 SPM 自己的 Package.resolved:

css 复制代码
 [  { "url": "https://github.com/SnapKit/SnapKit" },  { "url": "https://github.com/iAmMccc/SmartCodable.git", "version": "4.3.7" } ]

url 必填,version 可选。不填版本就拉默认分支最新代码,填了就 checkout 到对应 tag。

执行脚本

bash 复制代码
 ./Packages/scripts/fetch-packages.sh

脚本做的事情:

  1. 读取 packages.json,从 URL 自动解析库名
  2. 没下载过的 → git clone
  3. 已存在且版本匹配 → 跳过
  4. 已存在但版本变了 → fetch + checkout

脚本自动继承终端的 http_proxy / https_proxy,所以你终端能翻墙,脚本就能翻墙。

执行结果长这样:

css 复制代码
 [下载] SnapKit
 [下载] SmartCodable 4.3.7
 ​
 完成。下载: 2 / 更新: 0 / 跳过: 0 / 失败: 0

第二次跑:

css 复制代码
 [跳过] SnapKit
 [跳过] SmartCodable 4.3.7
 ​
 完成。下载: 0 / 更新: 0 / 跳过: 2 / 失败: 0

已经有的不会重复下载。

Xcode 引用

File → Add Package Dependencies → Add Local → 选 Packages/Caches/SnapKit。

每个库只需要添加一次。之后不管你 Reset 多少次,本地文件都在,Xcode 直接用。

日常工作流

场景 操作
新增依赖 packages.json 加一条 → 跑脚本 → Xcode Add Local
更新版本 改 version → 跑脚本 → Xcode Resolve
新同事加入 clone 项目 → 跑一次脚本 → 齐活
Reset Package 无影响,本地文件还在

一键安装

如果你想直接用,在项目根目录跑:

bash 复制代码
 curl -sL https://raw.githubusercontent.com/iAmMccc/ai-essentials/main/install-skill.sh | bash -s spm-local

会自动生成 Packages/ 目录结构、下载脚本、示例配置,并把 Packages/Caches/ 加进 .gitignore。

几个细节

  • Packages/Caches/ 不提交到 Git,三方库源码不应该进仓库
  • 如果某个库是另一个库的 SPM 依赖(比如你用的 A 库依赖了 B 库),B 也要一起本地化,否则 Xcode 还是会去网上找 B
  • 脚本依赖 python3 解析 JSON,macOS 自带,不需要额外安装

本质上就一句话:让终端替 Xcode 干网络的活。终端能走代理,下载一次就缓存到本地,Xcode 只负责引用本地文件。三个问题同时解决。

相关推荐
songgeb4 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
软泡芙5 小时前
【iOS】swift启动屏显示黑屏
ios
用户69371750013846 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
Layer6 小时前
一些脱离 Mac 依赖的 Agent 操作 iPhone 实现
ios·ai编程·测试
用户69371750013848 小时前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
茶底世界之下8 小时前
一键裁方会丢掉什么?用 Awaking 给园林照片做两种画幅
ios
Marco_Marco13510 小时前
定位SDK接入实战:Android/iOS/鸿蒙三端怎么选、怎么接
android·ios·harmonyos
老李IT笔记1 天前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机
2501_915921431 天前
iOS应用耗电测试:使用Energy Log、Keymob和Instruments进行性能监控与能源消耗分析
android·ios·小程序·https·uni-app·iphone·webview
黑化旺仔1 天前
RunLoop 源码探索
ios·cocoa·xcode