
macOS 开发 - 使用 Sparkle 轻松实现 App 更新管理
在独立分发 macOS 应用时,你是否也为「怎么优雅地让用户自动更新」而头疼?🤯 别担心,Sparkle 框架就是解决方案!本文带你从原理到实践,手把手实现 App 的自动更新 🚀。
在 macOS 应用分发上,App Store 渠道依托平台自带的版本管理机制,开发者只需关注版本提交与审核即可。而对独立分发的应用来说,构建一个可靠的更新管理系统就显得尤为重要。
历经多个产品的实践,个人认为 Sparkle 框架是更新管理的优选方案:不仅稳定可靠,还功能完善。下面分享具体的实现过程!
0. 工作原理
开始之前有必要简单介绍 Sparkle 的工作原理,方便后面步骤理解
0.1 网络服务端
- 托管一个 Appcast XML 文件,包含最新版本信息(版本号、下载链接、更新说明等)
- 提供应用安装包的下载服务,通常托管在 GitHub Releases 或 CDN 上
Appcast 文件和应用安装包都托管到同一个路径下,推荐使用 对象存储,我选择的是 CloudFlare R2 的存储,原因:
- 全球(包括国内)都可访问
- 存储有收费限制,但访问流量无限制
- 可自定义域名,直接把 Appcast 文件和应用包上传就能通过指定域名按目录访问了。
0.2 应用客户端
- 集成 Sparkle 框架,定期检查 Appcast URL 获取版本信息
- 对比本地版本与远程版本,发现更新时提示用户
- 下载新版本安装包,验证签名后自动替换旧版本并重启应用
整个流程就是:
App 问服务器"有更新吗?" → 服务器回答"有,在这里下载" → App 自动下载安装
开发者只需维护 Appcast 文件和上传新版本,用户即可享受无缝更新体验。
1. 安装依赖
在 Xcode 打开项目,Xcode 中点击 File → Add Package Dependencies...,输入链接: https://github.com/sparkle-project/Sparkle
选择 sparkle ,点击 Add Package 按钮,然后在弹窗中勾选 Add to Target 到项目的 Target 上,继续点击 Add Package 按钮即可添加。
2. 生成 Sparkle 密钥
需要找到本地依赖安装位置。
打开 Xcode 左侧 Navigator 的 Projects 面板,最下面找到 Sparkle。
右击选择 Show in finder ,新打开的 访达 窗口中会看到 sparkle 目录,切换到上一级目录(快捷键 ⌘+↑),可以看到 artifacts 目录。
找到 artifacts/sparkle/Sparkle/bin,其中包含多个可执行工具:
- generate_keys
- generate_appcast
右键其中的 generate_keys,选择 将 generate_keys 拷贝为路径,打开终端,粘贴回车执行:
复制其中 <string>标签内的内容,即为密钥:U0mxe9F6FlB/zDEiNcDPTkNRIFxxxxxxxxxxxxxxxx
同一台 Mac 上所有 Sparkle 应用的 SUPublicEDKey都相同,这是 Sparkle 的设计特性,无需担心。。generate_appcast工具路径用同样方式获取,后续会用到。
3. 配置 info
找到 info 配置的地方,需要按照下面配置 4 个选项:
其中 URL 与公钥需替换为你自己的项目路径和步骤 2 生成的密钥。
如:将文件托管在 CloudFlare R2 的 releases/lottiego 目录,则 Appcast 路径为 https://xxx.com/lottiego/appcast.xml。
4. 配置权限文件
找到项目中的 .entitlements 文件,添加以下内容:
可直接复制使用。
5. 沙盒开启网络(可选)
如果未开启 App Sandbox,可跳过此步骤。
勾选 Network 两个选项即可:
- Incoming Connetions(Server)
- Outgoing Connections(Client)
6. 添加 Sparkle 代码
6.1 实现菜单检查更新的按钮视图
在 Xcode 中新建 CheckForUpdatesView.swift 文件,示例代码如下:
这里只是一种实现方式,同理可以任意实现 UI 上的交互。
6.2 初始化更新控制器并添加菜单按钮
在主入口 @main 的 App 文件中添加:
核心在于 updaterController 的初始化与 .commands 中添加的菜单项。
7. 打包
至此 Sparkle 的集成已完成,应用已具备检查和更新功能。接下来执行常规打包,具体步骤可参考我之前的文章:
8. 生成 appcast.xml
打包文件我通常的命名规则:[App名称]-v[版本号].dmg,如 LottieGo-v0.1.0.dmg。
同时准备一个同名的 HTML 文件作为更新日志(支持多语言),如 LottieGo-v0.1.0.en.html / LottieGo-v0.1.0.zh.html。
比如 LottieGo-v0.1.0.en.html 内容:
使用步骤 2 中获取到的 generate_appcast 工具,在打包好的 DMG 和 日志 HTML 文件所在目录下执行:
比如我在 LottieGo 的执行过程(注意下面不只是命令,还有执行命令中的所有显示文本):
会生成 appcast.xml 文件,自动解析 DMG 与 HTML 文件并写入更新信息,如果目录中存在以往版本的 DMG,会生成跨版本之间的增量更新的 delta 包,相应信息也会出现在 appcast 中。
Sparkle 通过 build 号作为版本标识符,自动生成 delta 差异包。
9. 发布相关文件
上面我们整个过程中的文件,只需要发布:
- LottieGo-v0.1.0.en.html
- LottieGo-v0.1.0.zh.html
- LottieGo-v0.1.0.dmg
- appcast.xml
当目录下存在多个版本时,Sparkle 会自动生成 delta 包(增量更新),可显著减少用户更新下载量。记得将 delta 文件一并上传到对象存储中。
10. 测试
如果需要进行测试,请按以下步骤操作
- 临时将项目的 version 和 build 号各自递增 1
- 重复执行步骤 7、8、9
- 打开本地上一个版本的应用
- 在菜单栏点击 检查更新
如无异常,您将看到可用更新,新版本号应与您临时修改的版本一致。
参考
- Sparkle Guide - Enabling auto-update on SwiftUI Mac apps released as a DMG outside the Mac App Store
- Sparkle 开源仓库
如果喜欢关于 macOS 开发的内容,欢迎关注我的 twitter 帖子,当然也欢迎 Follow 我😉。
什么?你也对文中提到的 LottieGo 感兴趣,这是一款简洁漂亮也有实力的 Lottie 文件体积优化工具,下面👇是传送门🚪



