如何在没有 Mac 的情况下构建 iOS 应用
介绍如何通过 Expo EAS、租用云端 Mac 或 CI,在没有 Mac 的情况下构建并发布 iOS 应用,并比较费用、签名和 iPhone 测试方式。
即使没有 Mac,你也可以编写、构建、签名并发布 iOS 应用。但所有可行的方案都要借用别人的 macOS:Expo 的构建服务器、租用的 Mac,或者 CI 运行器。
如果你在 Windows 或 Linux 上开发,你手头可能已经有一个能运行的 React Native 或 Capacitor 应用,桌上放着一部 iPhone,而入门指南却让你打开 Xcode。可是 Xcode 根本装不到你的机器上。
本文会介绍绕开这个问题的几种正规方案、各自的成本,以及应用构建完成后如何测试。在云端构建并不难,真正难的是没有 Mac 时如何测试。
核心要点
- Xcode、
codesign和 iOS 模拟器只能在 macOS 上运行,因此所有不用 Mac 的方案,实际上都是在别人的 Mac 上执行构建。 - 对于 Expo 和 React Native 项目,
eas build --platform ios会在 Expo 的服务器上编译并签名应用,eas submit --platform ios则可以从 Windows 或 Linux 将其上传到 App Store Connect。 - 无论选择哪种方案,Apple Developer Program 都需要每年 99 美元,因为 App Store 签名和 TestFlight 分发都要求拥有会员资格。
- iOS 模拟器是一款 macOS 应用,所以在没有自己的 Mac 时,你需要通过 EAS 内部构建或 TestFlight 在实体 iPhone 上进行测试。
- 在非 Apple 硬件上安装 macOS(无论是黑苹果还是虚拟机)都违反 Apple 的许可条款。
为什么 Apple 的构建工具链必须依赖 macOS?
Xcode、xcodebuild、codesign 工具以及 iOS 模拟器都只能在 macOS 上运行。因此问题不在于要不要用 Mac(这是绕不开的),而在于由谁的 Mac 来干活。编译原生 iOS 代码、用分发证书为二进制文件签名、为 App Store Connect 打包,这些步骤全都在 Apple 的工具链中完成。下面介绍的每种方案都只是绕过这一限制,而没有消除它。
使用 Expo EAS 在没有 Mac 的情况下构建 iOS 应用
对于 React Native 或 Expo 项目,eas build --platform ios 会在 Expo 的服务器上编译并签名应用。登录 Apple Developer Program 账号后,EAS CLI 还能帮你生成分发证书和描述文件(provisioning profile)。对本文的大多数读者来说,这就是首选方案。
如果你刚接触 Expo,可以先阅读 Getting Started with Expo。Expo 构建配置指南中的完整流程如下:
# Create a project if you don't have one
npx create-expo-app@latest my-app
cd my-app
# Install the EAS CLI and sign in to your Expo account
npm install --global eas-cli
eas login
eas whoami # confirms which account you're signed in as
# Generate the build configuration for the project
eas build:configure
# Build a signed iOS binary on Expo's servers
eas build --platform ios --message "First App Store build"
# Check build status and logs later
eas build:list
如果不想全局安装,可以在文档中出现 eas 的地方改用 npx eas-cli@latest。构建开始时,CLI 会询问是否由它来管理你的 iOS 凭据。如果选择“是”并登录 Apple 账号,你就完全不需要打开“钥匙串访问”或证书管理门户。
EAS Build 对 Expo 和 React Native 应用开箱即用,包括用 react-native 或 ignite-cli 创建的项目。Expo 表示它也支持其他原生项目。不过 Capacitor 没有官方的 EAS 指南,因此 Capacitor 团队通常会选择下文介绍的其他方案。
发布只需再执行一条命令:
eas submit --platform ios
EAS Submit 可在 Windows、Linux 或 macOS 上运行。它会将你的构建上传到 App Store Connect,待 Apple 处理完上传内容后,你就能在 TestFlight 中看到该构建。这一步需要付费的 Apple Developer 账号。登录方式可以是 App Store Connect API 密钥,也可以是 Apple ID 加 App 专用密码。
需要 Xcode 时租用云端 Mac
租用的云端 Mac 可以通过远程连接为你提供完整的 macOS 桌面。当你确实需要 Xcode 本身时,例如开发原生模块、进行 Xcode 级别的调试,或者处理没有托管构建方案的 Capacitor 项目,就可以选择这种方式。MacStadium 和 MacinCloud 等服务商都提供此类机器租赁。你能获得完全的控制权,但也要承担相应的运维工作:自行安装和更新 Xcode、管理证书和描述文件,并编写自己的构建脚本。
使用带 macOS 运行器的 CI
托管 CI 的 macOS 运行器适合已经将构建流程脚本化的团队。GitHub Actions 除了 Linux 和 Windows 运行器外,也提供托管的 macOS 运行器,其他 CI 服务商也有类似的 macOS 机器。运行器负责构建,但签名仍需你自己处理:你需要将证书和描述文件存储为密钥(secrets),并自行将它们接入流水线。如果你使用 Expo,也可以从 CI 触发 EAS 构建,同时保留 Expo 的托管签名。
应避免的方案:黑苹果与 macOS 虚拟机
在非 Apple 硬件上运行 macOS,无论是黑苹果,还是在 Windows 或 Linux PC 上的虚拟机,都违反 Apple 的许可条款。macOS Tahoe 软件许可协议禁止在任何非 Apple 品牌的计算机上安装或运行 macOS,仅允许在已运行 macOS 的 Mac 上使用 macOS 虚拟机。这两种方案都不要采用。
没有 Mac 如何测试 iOS 应用?
由于 iOS 模拟器是一款 macOS 应用,在没有自己的 Mac 时,你需要在实体 iPhone 上测试 iOS 应用,方式包括 EAS 开发构建或内部构建,以及 TestFlight。构建问题完全可以在云端解决,而测试才是没有 Mac 真正要付出代价的地方。
日常开发时,先添加开发客户端,再构建用于内部分发的版本:
npx expo install expo-dev-client
使用内部分发时,EAS 采用 Ad Hoc 描述文件。该描述文件会列出已批准设备的 UDID(设备唯一标识符),只有在构建时已列入该列表的设备才能安装此构建。使用以下命令注册你的 iPhone:
eas device:create
注册设备后,需要重新创建构建。注册之前生成的构建无法安装到该设备上。这些设备构建使用分发证书和 Ad Hoc 描述文件签名,两者都需要付费的 Apple Developer Program 账号。
如需更大范围的测试,TestFlight 每个应用最多可容纳 10,000 名外部测试员。你可以通过电子邮件邀请测试员或分享公开链接,但构建必须先通过 TestFlight App 审核。
还有一个缺口无法弥补:使用 Xcode 进行原生调试以及 iOS 模拟器仍然需要 macOS。遇到这种情况时,按需租用云端 Mac 即可。
费用是多少?该选哪种方案?
Apple Developer Program 每年费用为 99 美元,在许多地区 Apple 会以当地货币计费。这笔费用适用于所有不用 Mac 的方案,因为无论构建在哪里运行,App Store 签名和 TestFlight 分发都要求拥有会员资格。
| 方案 | 由谁运行 macOS | 你需要管理的内容 | 额外费用 |
|---|---|---|---|
| Expo EAS | Expo | 应用配置 | 提供免费套餐;参见 EAS 定价 |
| 云端 Mac | 租赁服务商 | Xcode、证书、脚本 | 参见服务商 |
| macOS CI 运行器 | CI 服务商 | 流水线、签名密钥 | 参见服务商 |
EAS 免费套餐每月提供少量 iOS 构建额度,并在较慢的队列中排队。付费套餐可让你进入更快的队列、支持更长的构建时间,还能付费提高并发构建数量。
对于在 Windows 或 Linux 上开发 React Native 或 Expo 应用这一常见场景,推荐使用 Expo 加一部实体 iPhone:支付 99 美元会员费,用 EAS 构建和签名,用内部构建和 TestFlight 进行测试,只在确实需要 Xcode 时才租用 Mac。
没有 Mac,意味着你是租用 Apple 的工具链,而不是购买硬件。构建和发布完全可以远程完成,你放弃的只是模拟器和原生调试。下一步:加入 Apple Developer Program,在项目中运行 eas build:configure,并在首次内部构建之前使用 eas device:create 注册你的 iPhone。
常见问题
没有 Mac 也没有付费 Apple 账号,能在 iPhone 上运行我的应用吗?
可以,用于原型开发时可以通过 Expo Go 实现。从 App Store 安装 Expo Go,在 Windows 或 Linux 上启动你的 Expo 项目,然后用 iPhone 相机扫描二维码即可。你项目的 Expo SDK 版本必须与 App Store 中 Expo Go 的版本一致。Expo Go 内置了一组固定的原生库,因此包含其他原生代码的库无法在其中运行。远程推送通知、通用链接(Universal Links)以及自定义应用名称和图标都需要开发构建,而在没有 Mac 的情况下将开发构建安装到 iPhone 上,需要付费会员资格。
一个 EAS 内部构建最多可以安装到多少台 iPhone 上?
每个会员年度最多 100 台 iPhone。Ad Hoc 构建只能安装在已注册到你 Apple Developer 账号的设备上,且 Apple 对每个产品系列分别计数,因此可以同时注册 100 台 iPhone 和 100 台 iPad。停用设备并不会释放其名额,只有在新的会员年度开始时,才能移除设备并将数量恢复到 100 台。如果测试人群更大,请使用 TestFlight,它无需注册设备。
每次修改代码都需要重新构建 iOS 应用吗?
不需要。EAS Update 可以将 JavaScript、样式和图片的变更通过 OTA(空中下载)方式推送到包含 expo-updates 库的构建中,用户在下次启动应用时即可获得新版本。原生层面的变更,例如添加包含 Swift 或 Objective-C 代码的库,仍然需要新的 EAS 构建;对于上架应用,还需要重新提交到 App Store。首次引入 expo-updates 的那个构建本身也必须是全新构建。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k