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

相关推荐
吠品19 小时前
Ubuntu下grep配合管道用的几个场景
ios·notepad++·iphone
人月神话-Lee19 小时前
【图像处理】框架设计——协议、值类型与工程化思维
图像处理·人工智能·ios·设计模式·架构·ai编程·swift
何乐乐19 小时前
【Taro 5.0 技术与实践】 - 高性能 iOS 渲染层与 TaroUI 跨端框架介绍
android·前端·ios
人月神话Lee19 小时前
【图像处理】框架设计——协议、值类型与工程化思维
ios·架构·图像识别
Digitally21 小时前
适用于 iPhone 的 iTunes 替代方案
ios·iphone
二蛋和他的大花21 小时前
高德地图 Flutter 插件:跨 Android / iOS / HarmonyOS 的完整实现
android·flutter·ios
巴博尔1 天前
UNIAPP中NVUE页面 动画
android·前端·javascript·ios·uni-app
2601_955767421 天前
圆偏振光膜与AR抗反射膜原理评测:scinique双护技术如何实现“一柔一清”?
ios·ar·iphone·圆偏振光·磁控溅射
人月神话-Lee1 天前
【图像处理】图像导出与工业级压缩策略——从像素到文件的最后一公里
图像处理·人工智能·ios·ai编程·swift