首页
看点啥
插画图片
首页 科技看点 构建和发布 Mac 及 iOS 应用程序而无需打开 Xcode

构建和发布 Mac 及 iOS 应用程序而无需打开 Xcode

2026-07-14 0

最近,我听到几位与苹果相关的播客主持人谈论 Xcode 有多糟糕,以及苹果需要通过让 Xcode 不那么难以理解来改进 Mac 和 iOS 应用的“氛围编码”体验。他们说得没错,但我不明白他们一开始为什么要打开 Xcode。只要做一些预先工作,你就可以随心所欲地为 Mac 和 iOS 应用进行“氛围编码”,而无需再查看 Xcode。

构建和发布 Mac 和 iOS 应用程序而无需打开 Xcode

如果你对如何实现以下任何一项有疑问,请将 Claude Code 或你选择的 LLM 编码工具指向这篇博客文章,让它来解决。这正是它的职责:解决你不想亲自处理的问题。

一次性设置是唯一有摩擦的部分,所以我们先把它搞定。

安装 Xcode

你必须安装 Xcode,这是无法绕过的,因为构建依赖于 Xcode.app 内部的工具。

安装 Xcode 后,请确保它是选定的命令行工具链,而不是 /Library/Developer/CommandLineTools。如果检查的输出是 /Applications/Xcode.app/Contents/Developer,那你就没问题了:

如果它返回的是独立的 CommandLineTools 路径,请将其指向 Xcode。

注意:“命令行工具”这个名字可能会令人困惑。

这是因为有一个独立的命令行工具包,可以通过 xcode-select --install 获取,即 /Library/Developer/CommandLineTools 版本。它包含 clang 和 git,但不包含 iOS SDK、notarytool、devicectl 以及完整应用开发所需的其他项目。

完整的工具链位于 Xcode.app 内部,路径为 /Applications/Xcode.app/Developer,它包含你所需的一切。如果你已安装 Xcode,则无需再安装独立的命令行工具。

安装 XcodeGen

Xcode 及其命令行工具不足以自动生成和管理 Xcode 项目。为此,你需要 XcodeGen。你可以从 GitHub 下载它,或使用 homebrew 安装:

简而言之,Xcode 项目实际上是 macOS 使其看起来像文件的文件夹,其中包含创建和编译应用所需的所有项目信息。Xcode 会不断修改文件和文件引用,这会给 git 仓库带来问题。

XcodeGen 创建一个 project.yml(YAML)文件,其中包含所有项目设置,然后在每次构建时使用该 project.yml 文件重新生成整个 .xcodeproj 文件夹。只有 YAML 文件需要提交到 git,整个 .xcodeproj 可以从 git 的角度忽略。

一次性配置 Xcode

你确实需要初始设置 Xcode,以便之后再也不用看它一眼。

Xcode 许可协议和附加组件

首先,要么接受其许可协议并安装附加组件,要么通过命令行完成:

在 Xcode 中设置你的 Apple 开发者账户

接下来,打开 Xcode,点击 Settings → Accounts,然后点击 + 添加你的账户。

注意:你必须拥有付费的 Apple 开发者账户才能分发和公证你的应用。

你会希望它们经过公证,以便在你的 Mac 和 iOS 设备上安装时,操作系统不会将其视为恶意软件并删除它们。

创建 Developer ID Application 证书

完成后,创建一个 Developer ID Application 证书(Settings → Accounts → 你的 Apple ID → Manage Certificates… → + → Developer ID Application),该证书用于签署发布的 .app 包。

请注意,Developer ID Application 证书和你的 Apple Development 证书是两个不同的东西。

Apple Development 身份用于在你自己的设备上构建和运行 —— 推送到你的 iPhone、本地调试。Developer ID Application 身份用于通过 Gatekeeper 并在他人 Mac 上运行的已公证 .app。发布脚本需要的是后者。

在 Xcode 中创建证书时,会将证书及其私钥安装到你的登录钥匙串中。私钥才是真正执行签名的,它无法重新下载 —— 所以不要删除它,并备份你的钥匙串。

如有疑问,请向你选择的 LLM 询问并让它帮助你设置。反正它就是为你使用 Xcode 的。

最后,

存储公证凭据 —— 一次性,在终端中完成

公证会将你签名的应用上传到 Apple 进行恶意软件扫描。notarytool 使用你一次亲密行为互创建的存储钥匙串配置文件进行身份验证 —— 它会提示输入应用专用密码,无法绕过该提示:

以下几点值得注意:

确认它已存储:

顺便说一下,我将我的应用专用密码存储在 Claude Code 可以访问的 1Password 保险库中。这样每当我创建新应用时,我可以告诉它为我创建公证凭据,它会知道从其 1Password 保险库中查找密码。使用 LLM 的初衷就是避免手动处理你不想做的事情。

设置 Local.xconfig 文件并将其添加到 .gitignore

实际签名需要你的团队 ID 和 bundle 前缀,我将它们放在 Local.xconfig 文件中:

再次提醒,如有疑问,请让 Claude Code 或你选择的 LLM 为你创建此文件。

设置智能体工具

创建部署脚本

我的应用部署通过一个名为 release.sh 的脚本处理,该脚本位于仓库内的 scripts 文件夹中。没有它,我就没有自动构建管道。

我让 Claude Code 为我创建了这个脚本:我大致告诉 Claude:我想归档、Developer ID 签名、公证、附加票据,并将此应用安装到 /Applications,而无需打开 Xcode。为我写一个脚本,完成整个流程,并在任何步骤失败时大声报错。

它不需要我解释流程,因为流程不是秘密 —— 使用 xcodebuild 归档,使用 -exportArchive 和 ExportOptions.plist 导出,使用 notarytool --wait 提交,使用 stapler 附加票据,使用 spctl 检查。这是发布 Developer ID Mac 应用的文档化、常规方式,模型知道这一点。它需要我提供的是项目特定的内容:scheme 名称、团队 ID、公证配置文件名称、结果安装位置。

然后它写了一个初稿,我们运行它,它失败了,我们修复了它。这个循环不是失败模式,这只是过程。我总是将 AI 工作流视为进行中的工作,但很快你就可以停止调整,开始工作了。

这是我某个应用仓库中的实际脚本:

它看起来比实际更复杂,但它是一系列你需要知道必须执行的步骤。再次强调,这就是为什么你要与 LLM 对话,告诉它你想要什么,并让它帮你构建工作流。

一些注意事项:

set -euo pipefail 会在任何命令失败时立即停止脚本,而不是继续执行。不会有看起来像成功但实际未完成的状态。

cd "$(dirname "$0")/.." 意味着脚本会跳转到仓库根目录,无论你从哪里调用它,所以 ./scripts/release.sh 在你在仓库根目录或深入三级目录时都能工作。

预检块检查 xcodegen 是否存在以及公证配置文件是否实际存储,以免在注定失败的第五步上浪费五分钟进行归档。

最后两个步骤重新验证已安装的包,而不仅仅是导出的包。这是双重保险,但我曾遇到复制步骤静默损坏包的情况,我宁愿从脚本中发现,而不是三天后 Gatekeeper 删除我的应用时才发现。

创建 CLAUDE.md 或 AGENTS.md

release.sh 为你提供一键部署。CLAUDE.md(或 AGENTS.md,适用于几乎所有其他模型)是让智能体实际使用它的方法,而无需每次都被告知。

我在与 Claude 反复讨论构建过程后,让 Claude 为我创建了 CLAUDE.md。现在每当我创建新应用时,我会告诉它参考我其他应用的仓库并使用相同的方法。

这就是整个一次性设置。从现在开始,无需鼠标。

构建实际运行方式 —— 无 GUI 参与

以下所有内容都是普通的命令行调用。Xcode.app 永远不会启动;这些工具位于其中但可独立运行。这正是 Claude Code 通过其 shell 执行的内容。

快速、未签名检查

对于“是否能编译 / 测试是否通过”,你根本不需要签名:

CODE_SIGNING_ALLOWED=NO 给你一个临时签名构建:它可以编译并在模拟器中运行,但 Gatekeeper 会拒绝它,iCloud KVS 和 App Group 等权限不会绑定。这是快速的内部循环。

Mac 发布流程

一个命令完成整个可发布流程 —— 来自第二部分的脚本:

归档、Developer ID 导出、公证、附加票据、验证、安装。如果任何步骤失败,它会停止并告诉你哪个步骤出错。需要不同的公证配置文件?覆盖它:TZED_NOTARY_PROFILE= ./scripts/release.sh。

无头部署到真实 iPhone

iOS 没有公证步骤 —— 这是 Mac 分发的概念。将构建部署到连接的 iPhone 是 xcodebuild 加上 devicectl,两者都在 Xcode 的工具链中:

devicectl list devices 列出连接和配对的设备及其 UDID。设备构建使用 Apple Development 身份(不是 Developer ID)加上开发配置文件签名,-allowProvisioningUpdates 会为你获取该配置文件。

无 GUI 时代码签名的工作原理

如果你只通过在 Xcode 中勾选框来签署应用,值得了解实际发生的事情,因为构建时根本不需要 GUI。

私钥执行签名。当你创建 Developer ID Application 证书时,Apple 会颁发证书,你的 Mac 会生成匹配的私钥,两者都存储在你的登录钥匙串中。codesign(xcodebuild 调用它)使用私钥对二进制文件进行签名;证书 —— 它链接到 Apple 的根证书 —— 会被嵌入,以便任何人都可以验证它。

自动签名为你选择身份。发布脚本使用 signingStyle: automatic,因此 xcodebuild 会根据团队 ID 选择正确的身份,并即时从 Apple 获取所需的配置文件。没有配置文件被提交到仓库。

权限在签名时绑定。每个目标都有一个 .entitlements 文件(沙盒、网络客户端、iCloud KVS、App Group)。这些只有在应用使用真实的团队身份签名时才生效,这也是临时签名构建无法发布的原因:没有团队前缀,iCloud 和 App-Group 权限会静默不绑定,你会花一个小时想知道为什么你的键值存储是空的。

公证不是签名。签名证明谁构建了应用。公证是单独的步骤,Apple 会扫描已签名的应用以查找恶意软件并颁发票据;附加票据使 Gatekeeper 在离线时信任应用。对于隐藏 UI 的菜单栏应用(LSUIElement),公证是防止 XProtect 标记它的原因。

密钥永远不会接触 git。签名私钥存储在登录钥匙串中。公证应用专用密码存储在 notarytool 钥匙串配置文件中。两者都不会写入仓库。

你可以手动验证任何已签名的构建:

智能体实际使用的内容

这里没有魔法。Claude Code 通过普通的、非交互式 shell 驱动所有这些 —— 没有特殊的“构建”MCP 服务器或插件在做聪明的事情。它使用的是 xcodebuild、xcrun notarytool、xcrun stapler、spctl、codesign、devicectl、xcodegen 和 swift。标准的 CLI 工具,与我们自己使用的相同。

粘合剂是第二部分中的 CLAUDE.md。它告诉智能体 notary-profile 约定、两个构建路径,以及 shipping 意味着 release.sh。结果是 Claude 直接运行它,而我无需在每个会话中重新解释。

唯一保持交互的步骤是 notarytool store-credentials,这是一个选择而不是限制:你可以传递 --password 并编写脚本,但这意味着将应用特定密码放在你的 shell 历史记录中。手动输入一次,让钥匙串或 1Password 保存它,下游的所有内容都会自动化。

为什么 Xcode 永远不需要打开

将 GUI 工作流与无头工作流并排放置,整个流程就完全对齐了:

GUI 只在一次性凭证设置时需要。之后,整个生命周期都是可编写脚本的,这正是 release.sh 最终完成的工作,也正因如此智能体可以端到端地拥有它,而我可以去做一些比观看进度条更有趣的事情。

如果你想自己尝试,顺序是:安装 Xcode 和 xcodegen,进行凭证设置,然后与 Claude 一起坐下来构建你自己的 release.sh 和 CLAUDE.md。最后这部分是实际工作,最多一两个小时。之后,"发布新构建"就变成了一句话。在第一个应用设置完成后,Claude Code 可以复制相同的设置来应用于未来应用。

喜欢(0)

上一篇

Apple的新语音API和Whisper:首个真实基准测试

Apple的新语音API和Whisper:首个真实基准测试

下一篇

苹果发布 iOS 27 等首个公测版:同步推送 macOS 27 Beta 3 修订版

苹果发布 iOS 27 等首个公测版:同步推送 macOS 27 Beta 3 修订版
猜你喜欢