我受够了 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 只负责引用本地文件。三个问题同时解决。

相关推荐
游戏开发爱好者83 小时前
TraceEagle 代理抓包详解,无感代理、去证书绑定与 HTTP/3 解密能力解析
网络协议·计算机网络·网络安全·ios·adb·https·udp
aiopencode4 小时前
SwiftUI Introspect生产环境完全指南:为什么它是安全可靠的选择
后端·ios
for_ever_love__4 小时前
iOS: 网络管理单例
学习·ios·objective-c
00后程序员张5 小时前
iOS加固技术路线全面解析:Bitcode模式、源码模式与汇编模式对比及爱加密优势
android·汇编·ios·小程序·uni-app·cocoa·iphone
ii_best15 小时前
更新!移动端开发软件按键安卓版&手机助手v5.1.0上线!本地AI识别全面解锁,脚本开发再升级
android·人工智能·ios·按键精灵
weixin_4038101318 小时前
03-iOS免越狱无线投屏-上传图片和视频到相册
ios·新媒体运营·跨境电商·ios自动化·ios投屏·ios智能体·ios脚本
2501_9160074718 小时前
SwiftUI 声明式语法与 Xcode 预览功能详解
ide·vscode·ios·swiftui·个人开发·xcode·敏捷流程
2501_9160088921 小时前
iOS IPA文件反编译与打包操作方法,拆包分析防护和加固打包
android·macos·ios·小程序·uni-app·cocoa·iphone
码云数智-大飞1 天前
iOS 卡顿排查指南:主线程阻塞与 UI 渲染优化实战
ui·ios
for_ever_love__1 天前
iOS:天气预报仿写总结
macos·ui·ios·objective-c·cocoa