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

相关推荐
智塑未来5 小时前
鸿蒙系统对比安卓、iOS,核心优势是什么?
android·ios·harmonyos
初雪云6 小时前
iOS 上架入门:证书、描述文件、IPA 上传到底是什么关系?
android·ios·自动化·产品经理·iphone
狂热开发者9 小时前
用 Typeoff 把会后口述整理成 Markdown 决策记录
人工智能·windows·macos·ios·安卓
MDM.Plus1 天前
苹果MDM技术演进:从远程控制到设备信任体系的构建
运维·服务器·安全·ios·mdm·手机店
韩曙亮1 天前
【Flutter】Flutter 进程保活 ③ ( 屏幕常亮设置 | Flutter 禁止息屏、关闭自动锁屏、屏蔽系统屏保 )
android·flutter·ios·屏幕常亮·禁止息屏
2501_915909061 天前
IPA 深度混淆是什么意思?从混淆强度到实际效果的解读
android·ios·小程序·https·uni-app·iphone·webview
apihz1 天前
经纬度制作高清卫星图片免费 API 接口详解
开发语言·ios·swift
黄林晴1 天前
KMP 正式支持 SwiftPM:CocoaPods 迁移配置指南
android·ios·kotlin
Tisfy2 天前
iOS:压缩和解压live图(.livp)——百度一刻相册+百度网盘识别支持
ios·百度网盘·livp·live图·一刻相册
唐诺2 天前
Objective-C 之 KVC 详解
ios·objective-c·kvc