使用 AI 代理构建 iOS 应用:实践者指南
# 借助 AI 代理更快地构建 iOS 应用。涵盖 Claude Code、Codex CLI、Xcode 26.3 原生支持、MCP、CLAUDE.md 模式、hooks,以及来自 8 款应用的实战经验。
TL;DR: 现在有三种代理运行时可以为 iOS 编写代码:Claude Code CLI 配合 MCP、Codex CLI 配合 MCP,以及 Xcode 26.3 的原生 Intelligence 代理。两个 MCP 服务器(包含 59 个工具的 XcodeBuildMCP 和包含 20 个工具的 Apple
xcrun mcpbridge)为代理提供了对构建、测试、模拟器和调试的结构化访问。本指南涵盖真实的 CLAUDE.md 模式、钩子配置以及对哪些有效、哪些会失败的诚实评估——内容来自 8 个生产环境 iOS 应用,共计 293 个 Swift 文件。17 代理在 SwiftUI 视图、SwiftData 模型、重构和构建错误诊断方面表现出色,但在 .pbxproj 修改、代码签名和可视化调试方面表现欠佳。”代理编写 Swift”和”代理交付 iOS 应用”之间的鸿沟,靠的是配置而非提示词来弥合。
我已经用 AI 编码代理构建了 8 个 iOS 应用。不是原型——是上架 App Store 的应用,集成了 HealthKit、Metal 着色器、SpriteKit 物理引擎、iCloud 同步、Live Activities、Game Center 排行榜,以及横跨 iOS、watchOS 和 tvOS 的多平台目标。这些应用中的每一行 Swift 代码,要么由代理编写、由我审查,要么由我编写、由代理重构。据我估计,代理承担了行级编写的大部分工作;我负责审查、范围把控以及那些需要人类判断的部分(视觉打磨、签名、性能调优、App Store 提交)。
本指南是我刚开始时希望存在的参考资料。它涵盖了完整的技术栈:使用哪个代理运行时、如何为结构化构建访问配置 MCP 服务器、CLAUDE.md 中应放入什么内容、哪些钩子可以防止代理破坏你的 Xcode 项目,以及——至关重要的——代理在哪些地方会失败、需要你接管。
关键要点
面向初次接触 AI 代理的 iOS 开发者:
- 从 Claude Code CLI + XcodeBuildMCP 开始。 这是最成熟的运行时,具有最深入的 MCP 工具覆盖。安装两个命令,在项目中添加一个 CLAUDE.md,代理就能在你无需复制错误信息的情况下完成构建、测试和调试。
- 绝不让代理修改 .pbxproj。 这是最重要的一条规则。一个用于阻止写入
.pbxproj和.xcodeproj/的 PreToolUse 钩子,能为你节省数小时的恢复时间。 - CLAUDE.md 是代理的入职文档。 在它上面投入的时间,会在每一次接触项目的代理会话中得到回报。
面向将 iOS 加入工作流的资深代理用户:
- MCP 改变了 iOS 构建循环。 在 MCP 之前,代理能编写 Swift 但无法验证是否能编译。有了 XcodeBuildMCP,代理可以编写代码、构建、读取结构化错误、修复错误并运行测试——全程自主完成。
- 三种运行时服务于不同需求。 Claude Code CLI 适合深度代理会话,Codex CLI 适合无头批处理工作,Xcode 26.3 原生代理适合不离开 IDE 的快速内联修复。
- 钩子基础设施可以延续。 你现有的 PostToolUse 格式化器、PreToolUse 拦截器和测试运行器钩子,只需稍作路径调整,就能在 iOS 项目中以完全相同的方式工作。
面向评估 AI 辅助 iOS 开发的团队负责人:
- 代理的有效性取决于项目文档,而非项目规模。 一个有详尽 CLAUDE.md 的 63 文件应用,产出的代理输出质量优于一个完全没有文档的 14 文件应用。
- .pbxproj 边界不可逾越。 代理无法可靠地编辑 Xcode 项目文件。你的工作流必须考虑手动将文件添加到 Xcode 目标的环节。
- 诚实的 ROI:在文档充分的项目上,代理可以承担实现的主体工作——这一点在 3 小时代理辅助工作交付的 15 文件电视应用中可见一斑(见下文案例研究)。剩余的工作——视觉打磨、签名、性能调优、App Store 提交——需要人类判断。
选择你的路径
| 你需要什么 | 前往这里 |
|---|---|
| 首次设置 MCP | MCP 设置:完整配置 — 安装两个服务器、验证、配置代理 |
| 为你的 iOS 项目编写 CLAUDE.md | iOS 项目的 CLAUDE.md 模式 — 来自 8 个应用的真实示例 |
| 比较三种代理运行时 | iOS 的三种代理运行时 — Claude Code vs. Codex vs. Xcode 原生 |
| 理解代理能做什么、不能做什么 | 代理擅长什么 和 代理不擅长什么 |
| 为 iOS 开发设置钩子 | iOS 开发的钩子 — 保存时格式化、.pbxproj 保护、测试运行器 |
| 深度参考(本页) | 继续阅读 — 从设置到高级模式的所有内容 |
如何使用本指南
这是一份超过 3,000 行的参考资料。从适合你经验水平的位置开始:
| 经验水平 | 从这里开始 | 然后探索 |
|---|---|---|
| iOS 和代理都是新手 | 先决条件 → MCP 设置 → 你的第一次代理会话 | CLAUDE.md 模式、哪些有效/无效 |
| iOS 开发者,代理新手 | 三种运行时 → MCP 设置 → CLAUDE.md | 钩子、架构模式 |
| 代理用户,iOS 新手 | 架构模式 → 代理不擅长什么 → CLAUDE.md | 框架特定上下文、高级工作流 |
| 两者都有经验 | 高级工作流 → 钩子 → 多平台模式 | 运行时对比、作品集 |
目录
- 作品集:8 个应用,293 个文件
- 先决条件
- iOS 的三种代理运行时
- MCP 设置:完整配置
- iOS 项目的 CLAUDE.md 模式
- 你的第一次代理会话
- 代理在 iOS 中擅长什么
- 代理在 iOS 中不擅长什么
- iOS 开发的钩子
- 适合代理的架构模式
- 框架特定上下文
- 多平台模式
- 高级工作流
- 真实案例研究
- 代理参与的项目生命周期
- 配置代理定义
- 代理辅助 iOS 的测试模式
- iOS 项目的上下文窗口管理
- 故障排查
- 代理在 iOS 中常见的错误
- 诚实的评估
- FAQ
- 快速参考卡
- 参考资料
相关资源
| 主题 | 资源 |
|---|---|
| Xcode 的 MCP 设置(较短的博客文章) | 两个 MCP 服务器让 Claude Code 成为 iOS 构建系统 |
| Claude Code CLI 完整参考 | Claude Code CLI:完整指南 |
| Codex CLI 参考 | Codex CLI:完整指南 |
| 钩子系统深度解析 | 爪子的解剖:84 个钩子作为编排层 |
| 代理架构模式 | 代理架构指南 |
作品集:8个应用,293个文件
在深入配置之前,先看看本指南的素材来源。这些都不是玩具项目——它们涵盖5个Apple框架、3个平台,以及iOS的全部复杂度范围,从一个14文件的健身追踪器到一个63文件的跨平台冥想计时器。
| 应用 | 技术栈 | 文件数 | 复杂度 |
|---|---|---|---|
| Banana List | SwiftUI + SwiftData + iCloud Drive同步 + 用于Claude Desktop的MCP服务器 | 53 | 完整CRUD、iCloud同步、向Claude Desktop暴露应用数据的自定义MCP服务器 |
| Ace Citizenship | SwiftUI学习应用 + FastAPI后端 | 26 | 客户端-服务器、REST API集成、测验引擎 |
| TappyColor | SpriteKit颜色匹配游戏 | 30 | 游戏循环、物理、触摸处理、粒子效果 |
| Return | 禅意冥想计时器——iOS 26+、watchOS、tvOS | 63 | HealthKit、Live Activities、Watch扩展运行时、TV焦点导航、iCloud会话同步 |
| amp97 | Metal着色器 + 音频可视化 | 41 | 自定义Metal渲染管线、音频分析、实时GPU计算 |
| Reps | SwiftUI + SwiftData健身追踪 | 14 | 最小可行应用、简洁的SwiftData模式 |
| Water | SwiftUI + SwiftData + Metal + HealthKit饮水追踪 | 34 | Metal流体模拟、HealthKit饮水量记录、小组件 |
| Starfield Destroyer | SpriteKit + Metal太空射击游戏 | 32 | 99个关卡、8种飞船、Game Center排行榜、Metal后处理 |
为何文件数量很重要:Agent的有效性与项目的可读性相关,而非项目规模。Return(63个文件)产出的Agent输出质量优于amp97(41个文件),因为Return拥有详细的CLAUDE.md,包含文件注释、架构图和明确的模式。无论文档质量如何,amp97的Metal着色器在本质上就更难让Agent进行推理。
前置条件
在为iOS开发设置任何Agent运行时之前:
App Store Connect截止日期:自2026-04-28起,上传至App Store Connect的应用必须使用Xcode 26或更高版本构建,并针对iOS 26、iPadOS 26、tvOS 26、visionOS 26或watchOS 26使用SDKs。12(macOS提交不受此要求约束。)如果您的团队仍在使用Xcode 16.x,本指南介绍的Agent辅助工具链同时充当了一种强制机制——下文涉及的MCP服务器无论如何都需要Xcode 26.3+才能运行。
必需项:
- macOS 15+(Sequoia)或macOS Tahoe
- 已安装并配置Xcode 26.3+(即xcrun mcpbridge的最低版本要求);推荐使用Xcode 26.4+,以获得Swift Testing图片附件、记录问题严重性、带崩溃日志的UI测试崩溃警告以及String Catalog编辑器改进等特性。13 Xcode 26.4.1(2026-04-16,构建版本17E202)是最新稳定版——仅修复bug。14
- 至少安装一个iOS Simulator运行时
- 一个Anthropic API账户(用于Claude Code)或OpenAI账户(用于Codex)
推荐项:
- 安装SwiftFormat(brew install swiftformat)——供保存时格式化hooks使用
- 安装SwiftLint(brew install swiftlint)——可选,但对样式强制很有用
- 熟悉终端——三种运行时均通过命令行运行或与之集成
验证您的Xcode安装:
# Check Xcode version
xcodebuild -version
# Expected: Xcode 26.3 or later (26.4+ recommended)
# Check available simulators
xcrun simctl list devices available
# Expected: at least one iPhone simulator
# Verify xcrun mcpbridge is available
xcrun mcpbridge --help
# Expected: usage information (not "command not found")
如果xcrun mcpbridge返回”command not found”,则需要Xcode 26.3或更高版本。请通过App Store或developer.apple.com安装或更新Xcode。注意:xcode-select --install仅安装Command Line Tools,其中不包含mcpbridge——您需要完整的Xcode.app。
iOS的三种Agent运行时
有三种不同的运行时可以编写、构建和测试iOS代码。它们并非可以互换——每种运行时都有不同的优势、不同的MCP集成模式以及不同的理想使用场景。
1. Claude Code CLI
它是什么: Anthropic推出的基于终端的agentic编码助手。可读取您的代码库、执行命令、修改文件,并通过MCP连接外部工具。
MCP集成: 完全支持XcodeBuildMCP和Apple的Xcode MCP。Agent通过MCP协议发现工具,并使用结构化参数调用它们。两个服务器共计59 + 20个工具。
安装配置:
# Install Claude Code (if not already installed)
claude --version # verify installation
# Add XcodeBuildMCP (59 tools — builds, tests, simulators, debugging)
claude mcp add XcodeBuildMCP \
-s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
# Add Apple Xcode MCP (20 tools — file ops, diagnostics, Swift REPL, previews)
claude mcp add --transport stdio xcode \
-s user -- xcrun mcpbridge
替代方案 — xcodebuildmcp init 自动安装器(v2.1.0+,2026-02-23):
如果您想跳过手动MCP配置,XcodeBuildMCP v2.1.0+附带了init子命令,可自动检测Claude Code、Cursor或Codex,并一步完成agent skills + MCP配置的安装:
xcodebuildmcp init
# Or without a global install:
npx -y xcodebuildmcp@latest init
参数:--print(将配置写入stdout以适配不受支持的客户端)、--uninstall(卸载)。如果您希望明确控制接入哪些MCP服务器以及作用范围,请跳过此步骤;上面的手动claude mcp add调用方式可以提供这种控制。15
最适合: 深度实现会话——构建新功能、跨多文件重构、调试复杂问题、自主运行构建-测试-修复循环。Claude Code的1M上下文窗口(搭配Opus 4.6)意味着agent可以将大多数中小型iOS项目装入工作记忆——根据我的经验,大约可容纳50个文件,具体取决于文件大小。
典型会话:
You: Add a new SettingsView with toggles for notifications and haptic feedback.
Use the existing Settings.swift pattern from TimerManager.
Build for simulator after implementation and fix any errors.
Claude: [reads Settings.swift, TimerManager.swift, existing views]
[creates SettingsView.swift]
[calls build_sim via MCP]
[reads structured error: missing import HealthKit]
[fixes import]
[calls build_sim again — success, 0 errors, 1 warning]
[calls test_sim — all tests pass]
与MCP出现之前的工作流相比,关键区别在于:agent从不要求您手动构建或粘贴错误输出。构建-报错-修复的循环是自主完成的。
2. Codex CLI
它是什么: OpenAI推出的基于终端的编码agent。概念上与Claude Code类似,但使用OpenAI模型(GPT-4o、o3),并且具有不同的权限模型。
MCP集成: Codex通过codex mcp add命令支持MCP。Apple的Xcode MCP可直接使用:
# Add Apple Xcode MCP to Codex
codex mcp add xcode -- xcrun mcpbridge
XcodeBuildMCP也可通过相同的npx命令与Codex配合使用:
# Add XcodeBuildMCP to Codex
codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp
最适合: 无人值守的批处理操作、CI/CD集成,以及希望从不同模型家族获得第二意见的任务。Codex的沙箱模式在隔离环境中运行代码,这对于会修改状态的破坏性操作(如测试套件运行)非常有用。
与Claude Code的关键区别:
- 使用OpenAI模型而非Claude模型
- 不同的上下文窗口大小和token经济学
- 沙箱优先的权限模型(默认更严格)
- MCP生态系统较小(经过测试的社区服务器更少)
- 提供Hooks系统(v0.119.0+),但成熟度不及Claude Code——事件类型较少,且没有条件性if字段
在iOS开发中何时选择Codex而非Claude Code:
当您希望获得模型多样性时使用Codex——让第二个agent审查第一个agent编写的代码,可以发现不同类别的错误。collab工作流(Claude构建,Codex审查)对iOS非常有效,因为某个模型家族认为正确的SwiftUI模式可能存在另一个模型才能发现的细微问题。Metal着色器和并发模式尤其能从双模型审查中受益。
3. Xcode 26.3 原生Agent
它是什么: Apple将AI编码agent直接集成到了Xcode的Intelligence面板中。从Xcode 26.3开始,您可以在Xcode Settings > Intelligence中将Claude Agent和Codex配置为智能服务提供方。
安装配置:
- 打开Xcode 26.3+
- 导航至 Settings > Intelligence
- 添加新的提供方:
- 对于Claude:选择”Claude Agent”,输入您的Anthropic API密钥
- 对于Codex:选择”Codex”,输入您的OpenAI API密钥
- Agent会出现在Intelligence侧边栏中,可在行内调用
最适合: 快速行内编辑、具备agent级推理能力的代码补全,以及不愿离开Xcode的开发者。原生集成意味着agent可直接访问Xcode的项目上下文——已打开的文件、构建目标、scheme配置——无需MCP桥接。
与CLI agent相比的局限: - 无Hook系统——无法强制保存时格式化或阻止对.pbxproj的写入 - 不加载CLAUDE.md——agent不会读取您的项目级配置文件 - 自主性有限——agent仅作用于当前文件或选区,而非整个项目 - 无subagent委派——复杂的多步任务无法并行化 - 无MCP服务器配置——agent仅使用Xcode内置工具
何时使用Xcode原生Agent:
适用于切换到终端代价过高的快速、局部编辑。”为这个model添加一个计算属性。”“为这个function编写一个单元测试。”“将这个view重构为使用@Observable。”——只涉及一两个文件且无需构建-测试循环的任务。
任何需要构建、测试、多文件重构或自主纠错的工作,请使用搭配MCP的CLI agent。
运行时对比矩阵
| 能力 | Claude Code CLI | Codex CLI | Xcode 26.3 原生 |
|---|---|---|---|
| MCP支持 | 完整(79个工具) | 完整(79个工具) | 仅Xcode内置工具 |
| Hook系统 | 是(成熟) | 是(基础,v0.119.0+) | 无 |
| CLAUDE.md / 项目配置 | 是 | codex.md等价物 | 无 |
| 自主构建-测试-修复 | 是(通过MCP) | 是(通过MCP) | 部分(仅行内) |
| Subagent委派 | 是(最多10个并行) | 否 | 否 |
| 上下文窗口 | 1M tokens(Opus 4.6) | 因模型而异 | 因提供方而异 |
| 多文件操作 | 完整代码库访问 | 完整代码库访问 | 当前文件 / 选区 |
| .pbxproj保护 | 通过hooks | 手动 | 不适用(原生使用Xcode) |
| 保存时格式化 | 通过PostToolUse hooks | 外部工具链 | Xcode设置 |
| 离线能力 | 无 | 无 | 无 |
| 计费模式 | Anthropic API使用量 | OpenAI API使用量 | 提供方API使用量 |
建议: 将Claude Code CLI作为主要运行时。使用Xcode 26.3原生agent进行快速行内编辑。使用Codex CLI进行审查和批处理操作。三者相辅相成,而非相互竞争。
MCP 配置:完整设置
MCP(Model Context Protocol)将代理从”编写Swift并寄希望于您能构建它”转变为”编写Swift、构建它、读取结构化错误并修复它们”。本节比博客文章更深入——涵盖两个服务器、所有安装方法、验证以及确保工具真正被使用的代理配置。
XcodeBuildMCP:用于无头iOS开发的59个工具
XcodeBuildMCP将xcodebuild、xcrun simctl和LLDB封装为59个结构化的MCP工具。它无需运行Xcode即可工作——整个构建-测试-调试周期通过Apple的命令行工具以无头模式运行。
安装选项:
# Option 1: Via npx (recommended — always uses latest version)
claude mcp add XcodeBuildMCP \
-s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
# Option 2: Via Homebrew (pinned version, manual updates)
brew install xcodebuildmcp
claude mcp add XcodeBuildMCP \
-s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- xcodebuildmcp mcp
# Option 3: Project-scoped (omit -s user)
claude mcp add XcodeBuildMCP \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
-s user标志使服务器在所有项目中全局可用。如需项目范围安装(例如只想在iOS项目中使用MCP,而不在Web项目中使用),请省略此标志。
-e XCODEBUILDMCP_SENTRY_DISABLED=true环境变量用于禁用崩溃报告遥测。XcodeBuildMCP默认包含Sentry,会发送包括文件路径在内的错误数据。除非您希望为该项目贡献诊断信息,否则建议选择退出。1
完整工具清单(8个类别下的59个工具):
| 类别 | 工具 | 功能说明 |
|---|---|---|
| 项目发现 | discover_projs, list_schemes, list_targets |
查找.xcodeproj/.xcworkspace文件,列出可用的scheme和target |
| 构建 | build_sim, build_device, build_mac |
按文件和行号输出结构化JSON错误/警告的构建 |
| 测试 | test_sim, test_device |
运行测试并返回每个方法的通过/失败结果 |
| 模拟器生命周期 | list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults |
创建、启动、管理和配置模拟器 |
| 设备管理 | list_devices, install_device, launch_device |
真机部署与管理 |
| 调试 | debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach |
完整的LLDB集成,包括断点和变量检查 |
| UI自动化 | snapshot_ui, screenshot, tap, swipe, type_text |
自动化交互与可视化捕获 |
| 项目脚手架 | create_project, add_file, add_package |
创建项目并添加依赖项 |
日常工作中最重要的工具:
-
build_sim——您将调用它数百次。它返回JSON,错误按文件、行号和严重程度分类。代理读取错误,导航到文件,并在您完全不动手的情况下进行修复。 -
test_sim——返回每个测试方法的结果。代理确切知道哪个测试失败以及为什么失败,而不仅仅是”测试失败”。 -
list_sims+boot_sim——无需记忆xcrun simctl标志即可管理模拟器。代理会发现可用的运行时并选择合适的设备。 -
discover_projs+list_schemes——项目自省。代理无需猜测您的scheme名称或workspace结构。 -
debug_attach_sim+debug_stack+debug_variables——远程LLDB调试。代理可以设置断点、检查变量并单步执行代码,而无需您打开调试器。
Apple Xcode MCP:连接Xcode的20个工具
Apple的MCP服务器通过xcrun mcpbridge随Xcode 26.3一起发布。它通过XPC(Apple的进程间通信框架)与运行中的Xcode进程通信,暴露任何CLI工具都无法访问的内部状态。
安装:
# Standard installation (global)
claude mcp add --transport stdio xcode \
-s user -- xcrun mcpbridge
# For Codex CLI
codex mcp add xcode -- xcrun mcpbridge
需要Xcode 26.3+和正在运行的Xcode进程。如果Xcode未打开,通过此服务器进行的每个MCP调用都将失败或挂起。XcodeBuildMCP没有此限制。
工具清单(5个类别下的20个工具):
| 类别 | 工具 | 功能说明 |
|---|---|---|
| 文件操作 | XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep |
在Xcode项目上下文中读取/写入文件 |
| 构建与测试 | BuildProject, GetBuildLog, RunAllTests, RunSomeTests |
使用Xcode内部构建系统进行构建和测试 |
| 诊断 | XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile |
实时代码诊断(不仅仅是构建错误) |
| 代码与文档 | ExecuteSnippet, DocumentationSearch |
Swift REPL执行与Apple文档搜索 |
| 预览 | RenderPreview |
无头SwiftUI预览渲染 |
Apple MCP独有的工具(XcodeBuildMCP中不可用):
-
DocumentationSearch——搜索Apple开发者文档,包括WWDC会议。对于Apple API问题,比网页搜索更快、更可靠。询问”HKQuantityType(.dietaryWater)是否有效?”,可以从源头获得明确答案。 -
ExecuteSnippet——在项目上下文中执行Swift REPL。代理可以验证API行为、测试类型转换并验证表达式,而无需构建整个应用程序。 -
RenderPreview——以无头方式渲染SwiftUI预览。代理可以检查视图是否能无错误地渲染,但无法评估视觉正确性(渲染结果作为数据返回,而非经过视觉检查)。 -
XcodeListNavigatorIssues——返回Xcode分析器的实时诊断,而不仅仅是构建错误。可捕获诸如未使用的变量、潜在的循环引用以及构建系统不会显示的弃用警告等问题。
为什么需要两个服务器
它们在构建和测试上存在重叠,但根本上有所不同:
┌─────────────────────────────────────────────────────────────────┐
│ MCP TOOL COVERAGE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ XcodeBuildMCP (59 tools) Apple Xcode MCP (20 tools) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Standalone │ │ Requires Xcode │ │
│ │ (no Xcode process) │ │ (XPC bridge) │ │
│ │ │ │ │ │
│ │ ✓ Simulators │ BOTH │ ✓ Documentation │ │
│ │ ✓ Real devices │ ┌─────┐ │ ✓ Swift REPL │ │
│ │ ✓ LLDB debugging │ │Build│ │ ✓ SwiftUI previews │ │
│ │ ✓ UI automation │ │Test │ │ ✓ Live diagnostics │ │
│ │ ✓ Project scaffold │ └─────┘ │ ✓ Analyzer issues │ │
│ │ ✓ Screenshot │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
XcodeBuildMCP适用于:构建-测试-调试周期。它无需打开Xcode即可工作,占用更少的系统内存,并提供更丰富的模拟器和设备管理功能。这是您的主要构建工具。
Apple Xcode MCP适用于:文档查询、Swift REPL验证、SwiftUI预览渲染和实时诊断。在需要这些功能的会话期间保持Xcode打开。
实际使用中:我大约90%的MCP调用使用XcodeBuildMCP,而Apple Xcode MCP用于文档和REPL验证。代理在构建和测试时默认使用XcodeBuildMCP,因为它更快(没有Xcode进程开销)且更可靠(没有XPC依赖)。
验证
安装两个服务器后,验证它们是否已连接:
# List all configured MCP servers
claude mcp list
# Expected output includes:
# XcodeBuildMCP: npx -y xcodebuildmcp@latest mcp - Connected
# xcode: xcrun mcpbridge - Connected
如果服务器显示”Disconnected”或未出现:
- XcodeBuildMCP未连接:确保已安装Node.js(
node --version)。npx命令需要Node.js 18+。 - Apple Xcode MCP未连接:确保已安装Xcode 26.3+,并且
xcrun mcpbridge命令在终端中可用。至少打开Xcode一次以接受许可协议。 - 两者都未出现:重启Claude Code(在新终端中运行
claude)。会话中途注册的MCP服务器可能要等到重启后才会出现。
教代理使用MCP
安装MCP服务器是必要的,但仅此还不够。如果没有明确的指引,代理可能会回退到通过Bash运行xcodebuild(非结构化输出,浪费上下文token),或者使用网页搜索查找Apple文档(更慢、更不可靠)。
将以下内容添加到您的CLAUDE.md或代理定义中:
## 构建与测试 — 始终使用 MCP
对于所有构建操作,优先使用 MCP 工具而非原始 shell 命令:
- **构建**: `build_sim` / `build_device`(而非通过 Bash 调用 `xcodebuild`)
- **测试**: `test_sim` / `test_device`(而非通过 Bash 调用 `xcodebuild test`)
- **模拟器**: `list_sims`、`boot_sim`、`open_sim`(而非通过 Bash 调用 `xcrun simctl`)
- **调试**: `debug_attach_sim`、`debug_stack`、`debug_variables`
- **Apple 文档**: `DocumentationSearch`(而非使用 WebSearch 查找 Apple API)
- **Swift 验证**: `ExecuteSnippet`(而非通过 Bash 调用 `swift`)
- **预览**: `RenderPreview` 用于无头 SwiftUI 验证
MCP 返回结构化 JSON,而 Bash 返回非结构化文本。
结构化数据意味着消耗更少的 token,并能更好地诊断错误。
这一指引确保智能体首先选择 MCP 工具。如果没有这条指引,您会发现智能体通过 Bash 构造冗长的 xcodebuild 命令,消耗数千个上下文 token 来解析输出,有时还会误判实际错误。
iOS 项目的 CLAUDE.md 模式
CLAUDE.md 是项目中对智能体辅助开发最重要的文件。它是智能体的入职文档——决定了智能体是像一位读过架构文档的新员工,还是一位仅靠猜测的新人。
我维护的每个 iOS 项目都有 CLAUDE.md。以下是从全部 8 个应用中提炼出的有效模式。
必备章节
每个 iOS CLAUDE.md 都需要这六个章节,其余皆为可选。
1. 项目身份
# Return - Zen Focus Timer
**Bundle ID:** `com.941apps.Return`
**Target:** iOS 26+ / macOS Tahoe / watchOS 26+ / tvOS 26+
**Architecture:** SwiftUI with @Observable pattern, companion Watch and TV apps
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0
为何重要:智能体在编写任何代码之前都需要知道部署目标。以 iOS 17 为目标的智能体会使用 NavigationView 和 @ObservedObject;以 iOS 26 为目标的智能体则会使用 NavigationStack 和 @Observable。Bundle ID 关乎权限和 HealthKit 配置。Swift 版本决定了并发模型(async/await 还是回调,严格并发还是宽松并发)。
2. 带用途注释的文件结构
## File Structure
```
Return/
├── ReturnApp.swift # App entry, dark mode enforcement
├── ContentView.swift # Main timer view with theme backgrounds
├── TimerManager.swift # Timer state, logic, and repeat handling
├── AudioManager.swift # Sound playback with AVAudioPlayer
├── Settings.swift # Centralized settings with validation
├── SettingsSheet.swift # Settings UI
├── HealthKitManager.swift # Mindful session logging + cross-device sync
├── LiveActivityManager.swift # Lock Screen/Dynamic Island
├── Theme.swift # Theme definitions
├── ThemeManager.swift # Theme state management
├── VideoBackgroundView.swift # AVPlayer video backgrounds
├── GlassTextShape.swift # Core Text glyph paths for glass effect
├── GlassTimerText.swift # Timer text with glass material
└── Constants.swift # App constants
```
每个文件名后的内联注释绝非装饰。它们是您能写下的杠杆率最高的单一文档。当智能体决定将新功能添加到何处时,这些注释会引导它在第一次尝试就找到正确的文件,而不必通读所有文件来理解项目布局。
反模式: 列出文件却不加注释。TimerManager.swift 无法告诉智能体它处理的是状态、UI 还是两者兼有。TimerManager.swift # Timer state, logic, and repeat handling 则明确说明了什么应放在这里、什么不应放在这里。
3. 构建与测试命令
## Build & Test
Build for iOS simulator:
```bash
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
```
Run tests:
```bash
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```
Run tvOS tests:
```bash
xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test
```
**Prefer MCP tools** (`build_sim`, `test_sim`) over these raw commands.
MCP returns structured JSON with categorized errors.
即便智能体应当优先使用 MCP,也请保留原始命令。这些原始命令可作为后备文档,并明确给出 scheme 名称和 destination。
4. 关键模式与规则
## Key Patterns
### Observable Architecture
- ALL view models use `@Observable` (NEVER `ObservableObject`)
- ALL navigation uses `NavigationStack` (NEVER `NavigationView`)
- State management via `@Observable` classes with `@MainActor` isolation
### Settings Pattern
- Centralized `Settings.shared` singleton
- All settings bounded to valid ranges with validation
- Sound names validated against whitelist
- Thread-safe access via @MainActor
### Audio System
- `AVAudioPlayer` with `.playback` category (plays in silent mode)
- Silent audio loop for background execution
- Bell playback with completion callbacks and token-based staleness
这些模式可防止智能体引入不一致。如果没有显式的模式文档,智能体有时会在某个文件中使用 ObservableObject,在另一个文件中使用 @Observable,或者绕过现有的 Settings.shared 单例去新建一套设置机制。
5. 智能体绝对不可做的事
## Rules
- **NEVER modify .pbxproj files** — create Swift files, then I will add them to Xcode manually
- **NEVER modify .xcodeproj/ contents directly**
- **NEVER add new package dependencies** without asking first
- **NEVER change the deployment target**
- **NEVER modify entitlements files** unless explicitly asked
- **NEVER use NavigationView** — always NavigationStack
- **NEVER use ObservableObject** — always @Observable
- **NEVER use @StateObject** — always @State with @Observable
明确的禁止比含糊的期望更有效。智能体遵循否定约束比遵循肯定建议更可靠,因为前者是二元的(做/不做),而后者是启发式的(优先这样做/有时那样做)。
6. 框架特定上下文
此章节因应用而异。对任何具有非显而易见配置的框架,都应包含此节:
对 HealthKit 应用:
## HealthKit Configuration
- Entitlement: `com.apple.developer.healthkit`
- Info.plist keys:
- `NSHealthShareUsageDescription`: "Return reads your mindful minutes..."
- `NSHealthUpdateUsageDescription`: "Return logs meditation sessions..."
- Category types: `HKCategoryType(.mindfulSession)`
- Authorization checked on every write (user can revoke at any time)
- HealthKit is unavailable on tvOS — guard with `#if canImport(HealthKit)`
对 SwiftData 应用:
## SwiftData Models
### Model Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList`
- `GroceryItem` has optional `Category`
### Model Container Setup
- Configured in App struct with `modelContainer(for:)`
- Schema versioning: currently V2
- Migration plan: `GroceryMigrationPlan` handles V1 → V2
### Queries
- `@Query(sort: \GroceryItem.name)` for sorted fetches
- `@Query(filter: #Predicate { !$0.isCompleted })` for active items
- Always use `@Query` in views, `modelContext.fetch()` in managers
对 SpriteKit 应用:
## SpriteKit Scene Hierarchy
```
GameScene (SKScene)
├── backgroundLayer (SKNode, zPosition: -100)
│ └── StarfieldNode (custom, parallax scrolling)
├── gameLayer (SKNode, zPosition: 0)
│ ├── playerShip (PlayerNode, zPosition: 10)
│ ├── enemyContainer (SKNode, zPosition: 5)
│ └── bulletPool (SKNode, zPosition: 8)
├── effectsLayer (SKNode, zPosition: 50)
│ └── ParticleManager (manages explosion/trail emitters)
└── hudLayer (SKNode, zPosition: 100)
├── scoreLabel (SKLabelNode)
└── healthBar (HealthBarNode)
```
- Physics categories defined in `PhysicsCategory.swift` as bitmasks
- Contact detection via `didBegin(_ contact:)` on GameScene
- Bullet pooling: pre-allocate 50, recycle via `removeFromParent()` + re-add
对 Metal 应用:
## Metal Pipeline
- Render pipeline: `MetalView` → `Renderer` → `ShaderLibrary`
- Compute pipeline: `AudioAnalyzer` → compute shader → texture output
- Shared uniforms struct: `Uniforms` in `ShaderTypes.h` (bridged to Swift)
- Frame timing: `CADisplayLink` drives render loop
- Buffer triple-buffering: 3 in-flight frames with semaphore
### Shader Files
- `Shaders.metal` — Main render shaders (vertex + fragment)
- `Compute.metal` — Audio analysis compute kernel
- `PostProcess.metal` — Bloom and color grading
### DO NOT modify Metal shaders without testing on device.
Simulator Metal is not representative of device GPU behavior.
真实 CLAUDE.md 示例:Banana List(SwiftUI + SwiftData + iCloud + MCP 服务器)
下面是一个带注释的示例,展示了这六个章节如何为一个中等复杂度的应用协同工作。这是我用于 Banana List 的 CLAUDE.md 模式——一个包含 53 个文件的购物清单应用,具备 iCloud 同步以及一个自定义 MCP 服务器,用于将应用数据暴露给 Claude Desktop:
# Banana List - Grocery List App
**Bundle ID:** `com.941apps.BananaList`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData + iCloud Drive sync
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0
## Core Features
- Grocery lists with items, categories, and quantities
- iCloud Drive sync via SwiftData CloudKit integration
- Custom MCP server exposing list data to Claude Desktop
- Liquid Glass design system
- Haptic feedback on interactions
- Share sheets for list sharing
## 文件结构
```
BananaList/
├── BananaListApp.swift # App entry, model container setup
├── Models/
│ ├── GroceryList.swift # @Model: list with name, items, color
│ ├── GroceryItem.swift # @Model: item with name, quantity, category, isCompleted
│ ├── Category.swift # @Model: user-defined categories
│ └── SampleData.swift # Preview and test data
├── Views/
│ ├── ListsView.swift # Main list of grocery lists
│ ├── ListDetailView.swift # Items within a list
│ ├── ItemRow.swift # Single item row with swipe actions
│ ├── AddItemSheet.swift # New item form
│ ├── CategoryPicker.swift # Category selection with create-new
│ └── SettingsView.swift # App settings
├── Managers/
│ ├── CloudSyncManager.swift # iCloud Drive sync status and conflict resolution
│ └── HapticManager.swift # UIImpactFeedbackGenerator wrapper
├── MCP/
│ ├── MCPServer.swift # MCP server for Claude Desktop integration
│ ├── ListTools.swift # MCP tools: list CRUD operations
│ └── ItemTools.swift # MCP tools: item CRUD operations
└── Extensions/
├── Color+Extensions.swift # Custom color definitions
└── View+Extensions.swift # Reusable view modifiers
```
## SwiftData 模型
### 关系
- `GroceryList` 拥有多个 `GroceryItem`(级联删除)
- `GroceryItem` 属于一个 `GroceryList`(必需)
- `GroceryItem` 拥有可选的 `Category`
- `Category` 拥有多个 `GroceryItem`(删除时置空)
### 容器设置
```swift
@main
struct BananaListApp: App {
var body: some Scene {
WindowGroup {
ListsView()
}
.modelContainer(for: [GroceryList.self, GroceryItem.self, Category.self])
}
}
```
### 查询模式
- 列表:`@Query(sort: \GroceryList.name) var lists: [GroceryList]`
- 活动项目:`@Query(filter: #Predicate { !$0.isCompleted })`
- 按分类:获取后在内存中过滤(SwiftData 谓词限制)
## 构建与测试
```bash
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```
优先使用 MCP 工具(`build_sim`、`test_sim`)而非原始命令。
## 关键模式
### Observable + SwiftData
- SwiftData `@Model` 类自动符合 Observable
- 切勿向 `@Model` 类添加 `@Observable`(冗余,会引发警告)
- 在表单中对模型属性进行双向绑定时使用 `@Bindable`
- 在视图中使用 `@Query`,在非视图代码中使用 `modelContext.fetch()`
### iCloud 同步
- 通过 SwiftData CloudKit 集成自动完成
- 冲突解决:后写入者胜出(CloudKit 默认策略)
- 同步状态通过 `CloudSyncManager.shared.syncState` 暴露
- 通过在两个使用相同 iCloud 账户的模拟器上运行来测试同步
### MCP 服务器架构
- 作为本地 WebSocket 服务器运行在 8765 端口
- 暴露 6 个工具:listAll、getList、createList、addItem、completeItem、deleteItem
- Claude Desktop 通过 `~/.config/claude-desktop/config.json` 中的 MCP 配置连接
## 规则
- 切勿修改 .pbxproj 或 .xcodeproj 内容
- 切勿在不更新 SampleData.swift 的情况下更改模型架构
- 切勿使用 `ObservableObject`——SwiftData 模型已经是 Observable
- 切勿使用 `@StateObject`——对 `@Observable` 类使用 `@State`
- 切勿使用 `NavigationView`——始终使用 `NavigationStack`
- 切勿向 `@Model` 类添加 `@Observable` 宏
- 始终使用 `@Bindable` 对模型属性进行表单绑定
- 始终在两个模拟器实例上测试 iCloud 同步变更
真实 CLAUDE.md 示例:Reps(精简 SwiftData 应用——14 个文件)
对于小型项目,CLAUDE.md 可以非常简洁。以下是 Reps 的模式,这是一个 14 个文件的健身追踪应用。请注意,即便是简短的 CLAUDE.md 也涵盖了全部六个核心部分:
# Reps - Workout Tracking
**Bundle ID:** `com.941apps.Reps`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData
**Swift version:** 6.2
## File Structure
```
Reps/
├── RepsApp.swift # App entry, model container
├── Models/
│ ├── Workout.swift # @Model: workout with exercises, date, duration
│ ├── Exercise.swift # @Model: exercise with sets, reps, weight
│ └── ExerciseTemplate.swift # @Model: saved exercise definitions
├── Views/
│ ├── WorkoutListView.swift # Main list of workouts
│ ├── WorkoutDetailView.swift # Exercises within a workout
│ ├── ExerciseRow.swift # Single exercise with inline editing
│ ├── AddExerciseSheet.swift # Exercise selection from templates
│ ├── NewWorkoutView.swift # Start new workout flow
│ └── StatsView.swift # Progress charts and summaries
├── Managers/
│ └── WorkoutTimer.swift # Active workout timer
└── Extensions/
└── Date+Extensions.swift # Formatting helpers
```
## Build & Test
```bash
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
```
## SwiftData Relationships
- `Workout` has many `Exercise` (cascade delete)
- `Exercise` has optional `ExerciseTemplate`
- `ExerciseTemplate` standalone (nullify on exercise delete)
## Rules
- NEVER modify .pbxproj
- NEVER use ObservableObject — use @Observable
- NEVER use NavigationView — use NavigationStack
- @Model classes are already Observable — do not add @Observable macro
- Use @Bindable for form bindings to model properties
40 行 CLAUDE.md 用于一个 14 个文件的项目。撰写仅需 10 分钟,却能省下数小时的智能体困惑。
真实 CLAUDE.md 示例:Starfield Destroyer(SpriteKit + Metal——32 个文件)
游戏项目需要更多与框架相关的上下文。智能体需要理解场景图、物理类别和游戏状态机:
# Starfield Destroyer - Space Shooter
**Bundle ID:** `com.941apps.StarfieldDestroyer`
**Target:** iOS 26+
**Architecture:** SpriteKit + Metal post-processing + Game Center
**Swift version:** 6.2
## Game Overview
99 levels across 3 galaxies. 8 unlockable ships with different stats.
Game Center leaderboards and achievements. Metal shader post-processing
for bloom and screen effects.
## File Structure
```
StarfieldDestroyer/
├── StarfieldDestroyerApp.swift # App entry, Game Center auth
├── GameScene.swift # Main game scene, update loop
├── MenuScene.swift # Title screen, ship selection
├── Entities/
│ ├── PlayerShip.swift # Player node with physics, weapons, shields
│ ├── EnemyShip.swift # Enemy base class with AI behaviors
│ ├── Bullet.swift # Bullet pool node
│ ├── PowerUp.swift # Collectible power-ups
│ └── Boss.swift # Boss enemies (levels 33, 66, 99)
├── Systems/
│ ├── LevelManager.swift # Level progression, wave spawning
│ ├── PhysicsCategory.swift # UInt32 bitmask categories
│ ├── CollisionHandler.swift # Contact delegate methods
│ ├── ScoreManager.swift # Score tracking, multipliers
│ ├── ParticleManager.swift # Explosion, trail, shield emitters
│ └── AudioManager.swift # Sound effects, background music
├── UI/
│ ├── HUDNode.swift # Score, health, level display
│ ├── ShipSelectView.swift # SwiftUI ship selection (UIHostingController)
│ ├── GameOverView.swift # Game over screen with score submission
│ └── PauseMenu.swift # Pause overlay
├── Metal/
│ ├── MetalRenderer.swift # Post-processing render pipeline
│ ├── BloomShader.metal # Bloom post-process effect
│ └── ShaderTypes.h # Shared uniforms (bridging header)
├── Data/
│ ├── ShipData.swift # 8 ship definitions (speed, damage, shields)
│ ├── LevelData.swift # 99 level configurations
│ └── AchievementData.swift # Game Center achievement definitions
└── GameCenterManager.swift # Leaderboard/achievement submission
```
## SpriteKit Scene Hierarchy
```
GameScene (SKScene)
├── backgroundLayer (zPosition: -100)
│ └── StarfieldNode (parallax scrolling, 3 layers)
├── gameLayer (zPosition: 0)
│ ├── playerShip (zPosition: 10)
│ ├── enemyContainer (zPosition: 5)
│ ├── bulletPool (zPosition: 8) — pre-allocated 50 bullets
│ └── powerUpContainer (zPosition: 3)
├── effectsLayer (zPosition: 50)
│ └── ParticleManager (explosion + trail emitters)
└── hudLayer (zPosition: 100)
├── scoreLabel (SKLabelNode)
├── healthBar (custom SKShapeNode)
└── levelLabel (SKLabelNode)
```
## Physics Categories
```swift
struct PhysicsCategory {
static let none: UInt32 = 0
static let player: UInt32 = 0b1 // 1
static let enemy: UInt32 = 0b10 // 2
static let bullet: UInt32 = 0b100 // 4
static let powerUp: UInt32 = 0b1000 // 8
static let shield: UInt32 = 0b10000 // 16
static let bossBullet:UInt32 = 0b100000 // 32
}
// Contact pairs:
// player + enemy → damage
// player + powerUp → collect
// bullet + enemy → destroy
// player + bossBullet → damage
```
## Game State Machine
```
.menu → .playing → .paused → .playing
→ .gameOver → .menu
→ .bossIntro → .playing
→ .levelComplete → .playing (next level)
```
## Metal Post-Processing
- Bloom shader: `BloomShader.metal` — multi-pass Gaussian blur + additive blend
- Uniforms: `PostProcessUniforms { float intensity; float threshold; float2 resolution; }`
- Applied after SpriteKit renders each frame via `SKView.presentScene(:transition:)`
- DO NOT modify Metal shaders without testing on device
## Build & Test
```bash
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test
## 规则
- 切勿修改 .pbxproj
- 切勿修改 PhysicsCategory 位掩码(会破坏所有碰撞检测)
- 切勿在不理解渲染顺序的情况下更改场景层级的 z 排序
- 切勿在不同步更新 Swift 和 Metal 引用的情况下修改 ShaderTypes.h
- 通过继承 EnemyShip 来添加新敌人,而不是修改它
- 子弹池:通过 removeFromParent() + 重新添加来回收,切勿分配新对象
- Game Center:提交分数前始终检查 isAuthenticated
真实 CLAUDE.md:amp97(Metal + 音频可视化 — 41 个文件)
Metal 项目需要最多的框架特定上下文,因为代理无法验证视觉输出:
# amp97 - Audio Visualizer
**Bundle ID:** `com.941apps.amp97`
**Target:** iOS 26+
**Architecture:** Metal render pipeline + AVAudioEngine analysis
**Swift version:** 6.2
## Architecture
```
Audio Input (microphone/file)
→ AVAudioEngine tap
→ FFT (vDSP)
→ Frequency/amplitude buffers
→ Metal compute shader (analysis)
→ Metal render pipeline (visualization)
→ CADisplayLink (60fps)
→ MTKView
```
## File Structure
```
amp97/
├── amp97App.swift # App entry
├── Audio/
│ ├── AudioEngine.swift # AVAudioEngine setup, tap installation
│ ├── FFTProcessor.swift # vDSP FFT, frequency bin extraction
│ ├── AudioBuffer.swift # Ring buffer for audio data
│ └── MicrophoneManager.swift # Microphone permission, session config
├── Rendering/
│ ├── MetalView.swift # MTKView wrapper for SwiftUI
│ ├── Renderer.swift # Main render loop, pipeline state
│ ├── ShaderLibrary.swift # Compiled shader management
│ ├── BufferManager.swift # Triple-buffered uniform updates
│ └── TextureManager.swift # Offscreen render targets
├── Shaders/
│ ├── Shaders.metal # Vertex + fragment shaders
│ ├── AudioCompute.metal # Audio analysis compute kernel
│ ├── PostProcess.metal # Bloom, color grading
│ └── ShaderTypes.h # Shared uniforms (bridging header)
├── Visualizations/
│ ├── WaveformViz.swift # Oscilloscope-style waveform
│ ├── SpectrumViz.swift # Frequency spectrum bars
│ ├── CircularViz.swift # Radial visualization
│ └── VizSelector.swift # Visualization switching
├── Views/
│ ├── MainView.swift # Full-screen viz with overlays
│ ├── ControlsOverlay.swift # Play/pause, viz selection, gain
│ └── SettingsView.swift # Audio source, sensitivity
└── Extensions/
├── SIMD+Extensions.swift # Vector math helpers
└── Color+Metal.swift # UIColor → float4 conversion
```
## Metal Pipeline
### Uniforms (ShaderTypes.h)
```c
typedef struct {
float time;
float2 resolution;
float audioLevel; // 0.0-1.0 RMS amplitude
float frequencyBins[64]; // FFT output, normalized
float4x4 transform;
} Uniforms;
```
### Render Pipeline
1. Compute pass: AudioCompute.metal processes FFT data → texture
2. Render pass: Shaders.metal reads texture + uniforms → visualization
3. Post-process pass: PostProcess.metal applies bloom → final output
### Buffer Management
- Triple buffering with DispatchSemaphore(value: 3)
- Uniforms updated per-frame on CPU, consumed by GPU 1-2 frames later
- Audio data ring buffer: 4096 samples, lock-free single producer/consumer
## Rules
- NEVER modify ShaderTypes.h without updating BOTH Swift and Metal sides
- NEVER exceed 64 frequency bins (fixed buffer size in shader)
- NEVER test Metal visual output in simulator — device only
- NEVER modify the audio engine tap format (48kHz, mono, float32)
- Triple buffer discipline: always signal semaphore in completion handler
- Audio session: .playAndRecord category with .defaultToSpeaker option
根据项目规模扩展 CLAUDE.md
合适的细节程度取决于文件数量和框架复杂度:
| 项目规模 | CLAUDE.md 深度 | 示例 |
|---|---|---|
| 小型(< 20 个文件) | 标识 + 文件列表 + 规则 | Reps(14 个文件):基本 SwiftData 模式、构建命令、禁止事项 |
| 中型(20-40 个文件) | + 框架上下文 + 关键模式 | TappyColor(30 个文件):SpriteKit 场景层级、物理类别、游戏循环 |
| 大型(40+ 个文件) | + 架构图 + 关系映射 + 多目标信息 | Return(63 个文件):跨平台架构、会话同步图、各平台差异 |
| 专业型(Metal/GPU) | + 管线图 + 共享类型定义 + 缓冲区布局 | amp97(41 个文件):渲染管线阶段、uniform 结构、缓冲区管理 |
过度记录的成本几乎为零(代理会跳过不需要的部分)。记录不足的成本却很高(代理会编造与您代码库相冲突的模式)。
CLAUDE.md 检查清单
为 iOS 项目创建或审查 CLAUDE.md 时,请使用此检查清单:
- [ ] 已指定 Bundle ID 和部署目标
- [ ] 已说明 Swift 版本和架构模式
- [ ] 文件结构带有内联用途注释
- [ ] 构建命令包含正确的 scheme 和 destination
- [ ] 测试命令包含正确的 scheme 和 destination
- [ ] 已注明 MCP 偏好(”prefer build_sim over xcodebuild”)
- [ ] @Observable 规则(绝不使用 ObservableObject)
- [ ] NavigationStack 规则(绝不使用 NavigationView)
- [ ] .pbxproj 禁止规则
- [ ] 框架特定上下文(HealthKit 权限、SwiftData 关系、SpriteKit 层级、Metal 管线)
- [ ] 已记录平台可用性守卫(#if canImport、#if os)
- [ ] 已记录关键单例和共享模式
- [ ] 已注明已知限制或注意事项
您的第一次代理会话
在配置好 MCP 并在项目中放置好 CLAUDE.md 后,以下是有效的第一次会话演练。本示例使用 Claude Code CLI,但工作流程适用于任何运行时。
步骤 1:验证代理能否看到您的项目
You: Summarize this project. What scheme should I build with?
Claude: [reads CLAUDE.md]
[calls discover_projs via MCP]
[calls list_schemes via MCP]
This is Return, a zen meditation timer for iOS 26+, watchOS, and tvOS.
Available schemes: Return, ReturnWatch, ReturnTV, ReturnTests.
Primary scheme for iOS: Return.
如果代理没有引用您的 CLAUDE.md 内容,请检查该文件是否位于项目根目录(与 .xcodeproj 或 Package.swift 同一目录)。
步骤 2:运行健康检查构建
You: Build the Return scheme for iOS simulator and report results.
Claude: [calls list_sims — finds iPhone 16 Pro on iOS 26.2]
[calls boot_sim — boots the simulator]
[calls build_sim — builds the project]
Build succeeded. 63 source files compiled.
2 warnings:
- HomeView.swift:132 — UIScreen.main deprecated in iOS 26.0
- LogWaterIntent.swift:61 — Result of try? is unused
0 errors.
步骤 3:运行测试
You: Run all tests and report pass/fail.
Claude: [calls test_sim]
12 tests executed:
✓ TimerManagerTests (5/5 passed)
✓ SettingsTests (4/4 passed)
✓ ConstantsTests (3/3 passed)
All tests passed.
步骤 4:实现一个功能
You: Add a new "Rain" theme to the theme system. Follow the existing
pattern in Theme.swift and ThemeManager.swift. Include a rain
ambient sound. Build and test after implementation.
Claude: [reads Theme.swift — understands Theme struct pattern]
[reads ThemeManager.swift — understands theme registration]
[reads existing theme definitions]
[adds Rain theme to Theme.swift following existing pattern]
[registers Rain theme in ThemeManager.swift]
[calls build_sim — build succeeds]
[calls test_sim — all tests pass]
Added Rain theme:
- Theme.swift: new `static let rain` with video, cover, ambient
- ThemeManager.swift: added to `allThemes` array
- Build: success (0 errors, 2 existing warnings)
- Tests: 12/12 passed
Note: You'll need to add rain_ambient.wav to the project
and add the new Theme.swift changes to the Xcode target manually
(I did not modify .pbxproj).
代理关于不修改 .pbxproj 的说明,是 CLAUDE.md 中规则起作用的结果。如果没有这条规则,代理会尝试修改项目文件,并很可能将其损坏。
Agent在iOS开发中擅长的工作
以下任务是Agent能够稳定产出正确、可用于生产环境的成果,且只需极少人工审查的领域。
SwiftUI视图与修饰符
Agent对SwiftUI声明式语法有着深入的模式识别能力。视图组合、修饰符链、状态绑定与布局——这些都能很好地匹配Agent的训练数据,因为SwiftUI的API表面文档完善,模式高度一致。
Agent的擅长之处:
- 根据描述构建新视图(”创建一个包含X、Y、Z开关的设置面板”)
- 应用修饰符链(.glassEffect()、.sensoryFeedback()、.navigationTitle())
- 在布局模式之间转换(VStack转LazyVGrid,List转ScrollView)
- 为SwiftData模型实现@Bindable表单绑定
- 构建带有示例数据的预览提供者
能产出优秀结果的提示示例:
Create a SettingsView that matches the existing pattern in SettingsSheet.swift.
Include toggles for:
- Enable haptic feedback (Settings.shared.hapticsEnabled)
- Enable HealthKit logging (Settings.shared.healthKitEnabled)
- Show session history (navigation link to SessionHistoryView)
Use Liquid Glass styling with .glassEffect() on section backgrounds.
Follow the @Observable pattern, not ObservableObject.
具体性至关重要。”创建一个设置视图”会产出泛泛而谈的代码。”创建一个与SettingsSheet.swift中现有模式相匹配的SettingsView”则会产出与您代码库一致的成果。
SwiftData模型与查询
Agent能够可靠地处理SwiftData的@Model宏、关系以及@Query模式。该框架的声明式特性(与Django ORM或SQLAlchemy类似)能很好地映射到Agent在众多代码库中见过的模式。
Agent的擅长之处:
- 定义带有关系的@Model类
- 编写带有排序描述符和断言的@Query
- 通过modelContext实现CRUD操作
- 在不同schema版本之间制定迁移方案
- 预览数据与测试固件
Agent需要指导之处:
- 复杂的#Predicate表达式(SwiftData的断言DSL存在一些限制,Agent并不总能知晓——请在CLAUDE.md中记录已知限制)
- CloudKit同步配置(通过SwiftData自动完成,但Agent可能会尝试手动实现同步)
单元测试
对于iOS项目,Agent编写的单元测试质量始终很高。Agent熟悉XCTest模式、异步测试方法以及setup/teardown生命周期。
Write unit tests for TimerManager covering:
1. Initial state is .stopped
2. start() transitions to .running
3. pause() transitions to .paused
4. reset() returns to .stopped with original duration
5. Timer counts down correctly (test with 3-second duration)
Agent能够产出结构良好的XCTest用例,包含setUp()和tearDown()、恰当的断言以及针对计时器测试的异步处理。
重构与模式应用
Agent擅长机械式重构:将视图提取为组件、将ObservableObject转换为@Observable、从NavigationView迁移到NavigationStack,以及在多个文件之间应用一致的模式。
Refactor all views in the Views/ directory to use @Observable instead of
ObservableObject. Update @StateObject to @State, @ObservedObject to direct
property access, and @Published to plain properties.
Agent会有条不紊地处理每个文件,正确应用变换,并保持现有功能完好。这是高杠杆的工作——一项手工编辑需要一小时的重构,Agent能在几分钟内以近乎完美的准确度完成。
通过MCP诊断构建错误
借助结构化的MCP输出,Agent诊断构建错误的速度比大多数开发者都快。Agent读取错误JSON,定位到具体文件和行号,理解错误信息并应用修复——往往在一轮交互中即可完成。
Agent能够自主修复的错误: - 缺失的导入 - 类型不匹配 - 协议遵循缺口 - 已弃用的API用法(附带替代方案) - 缺失的必需初始化器参数 - 访问控制违规
Agent需要帮助的错误: - 类型解析歧义(多个模块定义了同一类型) - 复杂的泛型约束失败 - 宏展开错误(Agent无法看到展开后的宏输出)
模拟器管理
Agent通过MCP能够妥善处理模拟器的生命周期:
Boot an iPhone 16 Pro simulator on iOS 26, install the app, and take a screenshot.
Agent会调用list_sims查找可用运行时、boot_sim启动模拟器、build_sim构建并安装、screenshot截屏——全部通过结构化的MCP调用完成。
Agent在iOS中做得不好的方面
诚实盘点Agent失败的地方。了解这些边界可以避免挫败感,也能减少token浪费。
.pbxproj文件修改——绝对禁止
这是iOS Agent开发中最重要的一条规则。.pbxproj文件是Xcode的项目配置——一种带有UUID引用、构建阶段列表和目标成员关系的结构化文本文件。它名义上可供人类阅读,但对AI Agent来说几乎无法解析。
为什么Agent在.pbxproj上会失败: - 该文件使用一种自定义格式(不是JSON,也不是YAML,更不是XML),位置具有重要含义 - 每一条记录都通过UUID交叉引用——添加一个文件需要在3至5个不同的小节中保持一致地更新 - 一个字符放错位置就会损坏整个项目文件 - Xcode对.pbxproj的合并冲突解决本身就很脆弱——Agent的编辑会让情况更糟
当Agent编辑.pbxproj时会发生什么: 1. 编辑看上去成功了(Agent报告”文件已更新”) 2. Xcode拒绝打开项目(”项目文件已损坏”) 3. 您花费15到60分钟从git历史中恢复 4. 您学会添加PreToolUse钩子(参见Hooks)
正确的工作流程: Agent创建Swift文件。您手动将其添加到Xcode项目中(拖入Xcode,或选择File > Add Files)。每个文件只需5秒,却能避免数小时的恢复工作。
对于Swift Package Manager项目: 这个限制要轻得多。Package.swift是标准的Swift文件,Agent可以可靠地编辑。如果您的项目完全使用SPM(没有.xcodeproj),Agent就可以管理完整的项目结构。
复杂的Interface Builder / Storyboard编辑
如果您的项目使用Interface Builder(.xib文件)或Storyboard(.storyboard文件),Agent无法对其进行有意义的编辑。这些是带有自动生成的UUID、约束引用和outlet连接的XML文件,它们是为可视化编辑而设计的,并非用于文本编辑。
应对方法: 新视图全部使用SwiftUI。如果您的项目存在历史遗留的Interface Builder文件,请保持原样,新UI一律用SwiftUI构建。
性能优化
Agent能写出正确的代码,却不一定是高性能的代码。它无法对您的应用进行性能分析,无法识别瓶颈,也无法测量帧率。性能优化需要:
- Instruments分析(可视化工具,Agent无法访问)
- 对特定设备的GPU/CPU特性的理解
- 基于测量、迭代式的改动
这种局限会出现在以下场景: - Metal着色器优化(Agent能写出有效的Metal代码,但无法测量GPU帧时间) - SwiftUI视图body的复杂度(Agent创建深度嵌套的视图,导致重绘开销) - Core Data / SwiftData查询优化(Agent写出的查询是正确的,但在大数据集上可能很慢)
应对方法: 让Agent负责实现,您自己用Instruments做性能分析,然后请Agent应用您已经识别出的具体优化措施。
代码签名与配置文件
Agent除了读取错误信息以外,无法调试代码签名问题。配置文件管理、证书创建、权限配置以及App Store提交,本质上都是由人工操作的工作流程,涉及Apple Developer门户、Keychain Access以及Xcode的签名UI。
Agent能看到的内容: “Signing for ‘Return’ requires a development team.”
Agent看不到的内容: 您的证书是否过期、配置文件是否包含目标设备、bundle ID是否与App ID匹配,或者您的entitlements文件是否正确。
应对方法: 所有签名相关操作都在Xcode的Signing & Capabilities标签页中处理。不要让Agent调试签名失败的问题。
复杂的Metal着色器调试
Agent写出的Metal Shading Language(MSL)语法是正确的,但它无法验证视觉输出,也无法调试GPU端的问题。Metal着色器在GPU上执行——Agent没有任何反馈机制来判断着色器是否产生了正确的视觉效果。
Agent在Metal方面能做的事:
- 根据描述编写顶点和片段着色器
- 在Swift中搭建Metal渲染管线
- 为数据并行操作编写计算着色器
- 修复.metal文件中的编译错误
Agent在Metal方面做不到的事: - 验证着色器输出的视觉正确性 - 调试GPU性能(帧时间、占用率、内存带宽) - 诊断视觉伪影(条带、精度问题、错误的色彩空间) - 在不同GPU架构上测试(A系列与M系列的行为差异)
应对方法: 在物理设备上测试Metal着色器。Simulator的Metal实现不能代表设备上GPU的真实行为。可视化调试请使用Xcode的GPU Frame Capture。
视觉布局验证
Agent看不到您应用的UI。它能写出SwiftUI布局代码并验证其能够编译,但无法判断最终呈现的画面是否正确。一个偏离中心10像素、字重错误或元素重叠的视图,既不会触发构建错误,也能通过所有逻辑测试。
应对方法: 视觉上审阅所有UI改动。使用Xcode中的SwiftUI Previews(或通过Apple MCP使用RenderPreview进行无界面渲染)来验证布局。可考虑使用swift-snapshot-testing之类的库进行快照测试,以实现自动化的视觉回归检测。
iOS开发的Hooks
Hooks是在代理工作流的特定时点确定性执行的Shell命令。它们是强制执行机制——是”请不要编辑.pbxproj”(代理可能忽略的建议)与”你不能编辑.pbxproj”(硬性阻止)之间的区别。
有关Hook系统的背景知识,请参阅Claude Code hooks指南。本节涵盖iOS专属的hook模式。
PreToolUse:阻止.pbxproj写入
任何iOS项目中最重要的hook。它阻止代理写入.pbxproj文件、.xcodeproj/目录及其他由Xcode管理的文件:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files. Create Swift files and add to Xcode manually.\" >&2; exit 2; fi'"
}
]
}
}
将其放在项目根目录的.claude/settings.json中,或放入~/.claude/settings.json以实现全局保护。
工作原理:当代理尝试对任何匹配该模式的文件使用Edit或Write工具时,hook会运行,检测文件路径,向stderr输出警告,并以代码2退出(这会阻止该工具调用)。代理收到错误消息后会调整其做法。
它能拦截:
- 直接的.pbxproj编辑
- .xcodeproj/或.xcworkspace/目录内的任何文件
- Interface Builder文件(.xib、.storyboard)
PostToolUse:使用SwiftFormat保存时自动格式化
每当代理写入或编辑Swift文件时,自动对其进行格式化:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
}
]
}
}
要求:必须已安装SwiftFormat(brew install swiftformat)。
为何重要:代理生成的Swift在语法上正确,但不会始终遵循格式约定。SwiftFormat会规范化缩进、大括号位置和import排序。保存时格式化的hook意味着代理触及的每个Swift文件在你看到之前都已自动格式化。
可选:在项目根目录添加.swiftformat配置文件以自定义格式规则:
# .swiftformat
--indent 4
--allman false
--stripunusedargs closure-only
--importgrouping testable-bottom
--header strip
PostToolUse:自动运行SwiftLint
如果你使用SwiftLint,可在每次Swift文件编辑后运行它:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftlint lint --path \"$FP\" --quiet 2>/dev/null || true; fi'"
}
]
}
}
|| true可防止lint警告阻塞代理。如果你希望lint违规起到阻塞作用,将其去掉即可。
PostToolUse:变更后自动构建
为获得激进的反馈循环,可在每次Swift文件变更后触发构建:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then xcodebuild -scheme Return -destination \"platform=iOS Simulator,name=iPhone 16 Pro\" build 2>&1 | tail -5; fi'"
}
]
}
}
警告:这种做法代价昂贵。每次文件编辑都会触发构建。请谨慎使用——它在调试会话中最为有用,因为你希望获得即时的构建反馈。在常规开发中,让代理在准备好时通过MCP手动触发构建即可。
PreToolUse:阻止entitlements修改
保护你的entitlements文件免受代理意外修改:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.entitlements$\"; then echo \"BLOCKED: Do not modify entitlements files without explicit permission.\" >&2; exit 2; fi'"
}
]
}
}
iOS Hook组合配置
以下是我在所有iOS项目中使用的完整.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard|entitlements)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode-managed files. Create Swift files and add manually.\" >&2; exit 2; fi'"
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
}
]
}
}
这给你两项保证: 1. 代理无法损坏Xcode项目文件(PreToolUse阻止) 2. 代理触及的每个Swift文件都会被自动格式化(PostToolUse格式化)
适用于 Agent 的架构模式
并非所有 Swift 架构对 Agent 都同样友好。以下这些模式之所以效果最佳,是因为它们显式、一致,且在训练数据中得到了充分体现。
@Observable(切勿使用 ObservableObject)
面向 iOS 26+ 的项目应当独占式地使用 @Observable。这既是现代模式,也是对 Agent 友好的模式:
// CORRECT — @Observable
@Observable
@MainActor
final class TimerManager {
var timeRemaining: TimeInterval = 0
var state: TimerState = .stopped
func start() {
state = .running
// ...
}
}
// In a view:
struct TimerView: View {
@State private var timer = TimerManager()
var body: some View {
Text(timer.timeRemaining, format: .number)
}
}
// WRONG — ObservableObject (deprecated pattern)
class TimerManager: ObservableObject {
@Published var timeRemaining: TimeInterval = 0
@Published var state: TimerState = .stopped
}
// WRONG — @StateObject (deprecated pattern)
struct TimerView: View {
@StateObject private var timer = TimerManager()
}
为何 @Observable 对 Agent 友好: 该模式更简单(无需 @Published 注解),所有权模型更清晰(用 @State 替代 @StateObject 与 @ObservedObject 的区分),Agent 使用它时产生的 bug 也更少,因为活动部件减少了。
请在 CLAUDE.md 中记录这一点: 即便目标平台已设为 iOS 26,Agent 偶尔还是会回退到训练数据中的 ObservableObject 模式。明令禁止可避免此情况。
NavigationStack(切勿使用 NavigationView)
// CORRECT
NavigationStack {
List(items) { item in
NavigationLink(value: item) {
ItemRow(item: item)
}
}
.navigationDestination(for: Item.self) { item in
ItemDetailView(item: item)
}
}
// WRONG
NavigationView {
List(items) { item in
NavigationLink(destination: ItemDetailView(item: item)) {
ItemRow(item: item)
}
}
}
NavigationStack 自 iOS 16 起可用,是新代码应当采用的唯一导航模式。类型安全的 navigationDestination(for:) 模式可防止 Agent 创建错误的导航链接。
使用 SwiftData 进行持久化
对于由 Agent 协助的开发而言,SwiftData 模型是最干净的持久化模式:
@Model
final class GroceryItem {
var name: String
var quantity: Int
var isCompleted: Bool
var category: Category?
var list: GroceryList?
init(name: String, quantity: Int = 1) {
self.name = name
self.quantity = quantity
self.isCompleted = false
}
}
Agent 处理 SwiftData 的关键规则:
1. @Model 类自动遵循 Observable —— 不要再添加 @Observable
2. 表单绑定使用 @Bindable:@Bindable var item: GroceryItem
3. 视图中使用 @Query 获取响应式数据:@Query var items: [GroceryItem]
4. 非视图代码中使用 modelContext.fetch()
5. 关系删除需要明确的规则:.cascade、.nullify、.deny
Swift 6.2 并发
新项目应面向 Swift 6.2 严格并发模式:
// Actor isolation for shared mutable state
@MainActor
@Observable
final class DataManager {
var items: [Item] = []
func loadItems() async throws {
let fetched = try await api.fetchItems()
items = fetched // Safe: @MainActor isolated
}
}
// Sendable conformance for cross-actor transfers
struct Item: Sendable, Identifiable {
let id: UUID
let name: String
let createdAt: Date
}
给 Agent 的并发指南:
- 所有视图模型都标记为 @MainActor(避免数据竞争警告)
- 所有异步工作都使用 async/await(不使用 completion handler)
- 跨 actor 传递的值类型应实现 Sendable
- 在视图中使用 Task { } 进行异步初始化
- 仅在已通过测量确认存在性能需求时才使用 nonisolated
Liquid Glass 设计系统(iOS 26+)
iOS 26 引入了 Liquid Glass 设计系统。只要给出明确指引,Agent 能很好地处理它:
// Glass effect on containers
VStack {
// content
}
.glassEffect()
// Glass effect with tint
Button("Action") { }
.glassEffect(.regular.tint(.blue))
// Glass effect on navigation bars (automatic in iOS 26)
NavigationStack {
// content
}
// Navigation bar automatically uses glass material
// Custom glass shapes
RoundedRectangle(cornerRadius: 16)
.fill(.ultraThinMaterial)
.glassEffect()
在 CLAUDE.md 中加入:“在分区背景和卡片容器上使用 .glassEffect()。在 iOS 26 中,导航栏会自动采用玻璃材质。请勿用自定义材质手动重建玻璃效果 —— 应使用系统提供的修饰器。”
框架专属上下文
每个 Apple 框架对 Agent 都有专属的注意事项。本节涵盖 8 款应用中所使用的各个框架。
HealthKit
使用它的应用: Return、Water
HealthKit 需要谨慎处理权限和平台守卫:
// Always check availability and authorization
import HealthKit
@MainActor
@Observable
final class HealthKitManager {
private let store = HKHealthStore()
var isAuthorized = false
func requestAuthorization() async {
guard HKHealthStore.isHealthDataAvailable() else { return }
let types: Set<HKSampleType> = [
HKQuantityType(.dietaryWater),
HKCategoryType(.mindfulSession)
]
do {
try await store.requestAuthorization(toShare: types, read: types)
isAuthorized = true
} catch {
// User denied — do not retry automatically
}
}
}
HealthKit 的 Agent 规则:
- 始终用 HKHealthStore.isHealthDataAvailable() 进行守卫
- 切勿假设已获授权 —— 每次写入时都需检查
- 跨平台代码使用 #if canImport(HealthKit)(tvOS 上不可用)
- 切勿在本地存储超出 HealthKit 提供范围之外的健康数据
- Info.plist 中需同时包含 NSHealthShareUsageDescription 与 NSHealthUpdateUsageDescription
SpriteKit
使用它的应用: TappyColor、Starfield Destroyer
SpriteKit 的场景图模型需要给 Agent 明确的指引:
## SpriteKit Rules
- Scene hierarchy is a tree of SKNodes with zPosition ordering
- Physics bodies use category bitmasks (UInt32) for collision detection
- Node pooling: pre-allocate reusable nodes (bullets, particles)
- Never add nodes directly to the scene — use layer nodes for organization
- Update loop: `update(_ currentTime:)` runs every frame — keep it fast
- Actions: use SKAction sequences for animations, not manual property updates
- Textures: use texture atlases for performance (.atlas directories)
Agent 在 SpriteKit 上的强项: - 创建 SKAction 序列与分组 - 配置物理体与接触检测 - 实现游戏状态机 - 构建 HUD 叠加层
Agent 在 SpriteKit 上的弱项: - 对性能敏感的游戏循环(Agent 会在每帧加入不必要的工作) - 复杂的物理模拟(为追求精度,自定义物理优于 SKPhysicsBody) - 粒子效果调优(视觉相关,需多次迭代)
Metal
使用它的应用: amp97、Water、Starfield Destroyer
Metal 是 Agent 最难驾驭的框架。GPU 编程模型与 CPU 端的 Swift 有根本性差异,且 Agent 无法验证视觉输出。
## Metal Rules
- Shared types between Swift and Metal go in a bridging header (ShaderTypes.h)
- Triple buffer in-flight frames (semaphore with value 3)
- Test shaders on DEVICE, not simulator (Metal behavior differs)
- Compute shaders: threadgroup size must divide evenly into grid size
- Fragment shaders: output color must be in correct color space (sRGB or linear)
- DO NOT optimize shaders without Instruments GPU profiling data
Metal 项目的 CLAUDE.md 应包含: - Uniforms 结构体定义(在 Swift 与 MSL 之间共享) - 渲染管线状态的设置模式 - 缓冲区索引及其用途 - 已存在的着色器及各自的功能 - 已知的精度问题(half 与 float 的对比)
Live Activities
使用它的应用: Return
Live Activities 需要特定的配置,但只要文档化,Agent 能很好地处理:
## Live Activities
- ActivityAttributes defined in `TimerActivityAttributes.swift`
- ActivityKit framework: `import ActivityKit`
- Widget extension: `ReturnWidgets/ReturnLiveActivity.swift`
- Start: `Activity<TimerActivityAttributes>.request(attributes:content:)`
- Update: `activity.update(ActivityContent(state:staleDate:))`
- End: `activity.end(ActivityContent(state:staleDate:), dismissalPolicy:)`
- Push token: register for updates via `activity.pushTokenUpdates`
Game Center
使用它的应用: Starfield Destroyer
## Game Center
- Authentication: `GKLocalPlayer.local.authenticateHandler`
- Leaderboards: `GKLeaderboard.submitScore(_:context:player:leaderboardIDs:completionHandler:)`
- Achievements: `GKAchievement.report(_:withCompletionHandler:)` (takes `[GKAchievement]` array)
- Always check `GKLocalPlayer.local.isAuthenticated` before submitting
- Handle authentication failure gracefully (offline play must work)
多平台模式
Return涵盖iOS、watchOS和tvOS。使用智能体进行多平台开发需要明确的平台边界文档。
共享代码组织
Shared/
├── MeditationSession.swift # Data model (all platforms)
├── SessionStore.swift # iCloud sync (all platforms)
└── SessionHistoryView.swift # UI (adapts per platform)
Return/ # iOS-specific
ReturnWatch Watch App/ # watchOS-specific
ReturnTV/ # tvOS-specific
智能体规则:“如果文件位于Shared/中,更改将影响所有平台。如果文件位于平台目录中,更改是隔离的。在修改文件之前,始终检查文件位于哪个目录中。”
平台可用性守卫
// HealthKit: available on iOS and watchOS, not tvOS
#if canImport(HealthKit)
import HealthKit
// HealthKit code here
#endif
// ActivityKit: available on iOS only
#if canImport(ActivityKit)
import ActivityKit
// Live Activity code here
#endif
// WatchKit: available on watchOS only
#if os(watchOS)
import WatchKit
// Watch-specific code here
#endif
智能体指引:“使用平台特定框架时,始终使用#if canImport()或#if os()守卫。不要假设某个框架在所有目标上都可用。”
按平台调整UI
struct SessionHistoryView: View {
@Query var sessions: [MeditationSession]
var body: some View {
List(sessions) { session in
SessionRow(session: session)
}
#if os(tvOS)
.focusable()
#endif
#if os(iOS)
.swipeActions {
Button("Delete", role: .destructive) {
// delete
}
}
#endif
}
}
高级工作流
自主构建-测试-修复循环
最强大的模式:向智能体提供功能规范,让它自主迭代经过构建-测试-修复循环。
Implement a countdown timer that:
1. Starts from a user-selected duration (10, 20, or 30 minutes)
2. Shows remaining time with a circular progress indicator
3. Plays a bell sound on completion
4. Logs the session to HealthKit as mindful minutes
Build after each change. Fix all errors. Run tests when the build succeeds.
Continue until all tests pass and the build is clean.
智能体编写代码,通过MCP构建,读取结构化错误,修复它们并重复。一个原本需要5-10次人工构建-错误-修复循环的功能,现在可以在单次自主循环中完成。
何时奏效:具有明确验收标准的清晰定义功能。
何时失效:开放式功能(”让它看起来更美观”)、性能敏感代码,或任何需要视觉验证的内容。
iOS子智能体委托
Claude Code的子智能体系统适用于iOS项目:
Use a subagent to research the best approach for implementing
iCloud key-value store sync for meditation sessions across iOS,
watchOS, and tvOS. Report back with the recommended pattern.
子智能体在独立的上下文窗口中探索文档和代码模式,返回摘要,然后主会话实现推荐方案。这可以避免研究消耗您的主上下文。
跨应用模式应用
当您维护多个具有一致模式的iOS应用时,智能体可以将一个应用中的模式应用到另一个应用:
Look at how Settings.swift works in the Return project
(centralized singleton with validation). Apply the same pattern
to create a Settings.swift for the Water project.
智能体读取源模式,理解其结构,并在目标项目中创建一致的实现。
双智能体审查(Claude + Codex)
对于关键变更,使用来自不同模型家族的两个智能体:
- Claude Code编写实现
- Codex CLI在单独的过程中审查
# After Claude implements the feature:
codex "Review the changes in the last commit. Focus on Swift 6.2
concurrency correctness, SwiftData relationship integrity,
and potential retain cycles. Report issues only — no praise."
不同的模型家族会捕捉到不同类别的错误。这对于Metal着色器和并发模式尤为重要,因为这些地方很容易引入微妙的错误。
双重审查能捕捉到单次审查遗漏的问题:
| 问题类型 | Claude强项 | Codex强项 |
|---|---|---|
| SwiftData关系循环 | 中等 | 强(GPT-4o) |
| @MainActor隔离缺口 | 强 | 中等 |
| Metal缓冲区对齐 | 中等 | 中等 |
| 保留循环检测 | 强(Opus) | 强(o3) |
| API弃用感知 | 强(更新的训练数据) | 中等 |
| 并发竞争条件 | 强 | 强(捕捉不同模式) |
双重审查的目的不是发现更多错误,而是发现不同的错误。每个模型家族在其模式识别中都有不同的失效模式。
跨多个应用的批量操作
当框架或模式变更影响多个应用时:
# Update @Observable pattern across all projects
for project in BananaList Return Water Reps; do
cd ~/Projects/$project
claude -p "Audit all files for any remaining ObservableObject usage.
Convert to @Observable following the pattern in CLAUDE.md.
Build and test after changes." --dangerously-skip-permissions
done
请谨慎使用。--dangerously-skip-permissions标志是非交互模式所必需的,但它会绕过所有安全检查。请确保已配置PreToolUse钩子来保护.pbxproj文件。
使用Apple设备端LLM的应用
如果您的应用调用Apple的Foundation Models框架(例如用于离线摘要、分类或结构化输出生成),智能体需要了解提示预算。iOS 26.4在SystemLanguageModel中新增了两个API,取代了之前4096个token的猜测值:contextSize(模型在单次对话中可接受的最大token数)和tokenCount(for:)(async throws,返回给定提示实际消耗的token数)。16两者都是@backDeployed(before: iOS 26.4),因此可在所有支持FM的操作系统版本上使用,无需#available分支。
智能体在生成提示构造代码时应遵循的模式:
import FoundationModels
func budgetFor(prompt: String, reservedReply: Int = 256) async throws -> Int {
let model = SystemLanguageModel.default
let promptCost = try await model.tokenCount(for: prompt)
let budget = model.contextSize - promptCost - reservedReply
guard budget > 0 else { throw ContextError.promptTooLong }
return budget
}
如果您的应用涉及SystemLanguageModel,请将此模式添加到您的CLAUDE.md中。否则,智能体会回退到旧的4096硬编码值,并在搭载更大上下文窗口的设备上静默截断提示。tokenCount(for:)上的async throws签名至关重要——粘贴同步版本的智能体将无法编译通过。
真实案例研究
抽象的建议很容易给出。以下是来自 8 款应用的具体场景,展示了 AI 辅助 iOS 开发在实践中的运作方式——包括失败的经历。
案例研究 1:为 Return 添加 TV 应用(成功)
任务:为 Return 添加 tvOS 目标。Return 是一款冥想计时器,已经有 iOS 和 watchOS 版本。TV 应用需要支持 Siri Remote 导航、大屏幕 UI,以及与 iOS 应用的设置同步。
Agent 做得好的地方:
- 阅读了现有的 iOS TimerManager 并创建了 TVTimerManager,省略了 Live Activities 和 HealthKit(在 tvOS 上不可用)
- 为 Siri Remote 焦点导航创建了自定义按钮样式(TVCapsuleButtonStyle、TVCircleButtonStyle)
- 构建了 TVStepper 组件,用 +/- 按钮替代滚轮选择器(无法与 Siri Remote 配合使用)
- 通过 App Groups(group.com.941apps.Return)实现了设置同步
- 在共享代码中各处添加了 #if os(tvOS) 守卫
- 通过 MCP 使用 platform=tvOS Simulator,name=Apple TV 进行构建和测试
我必须手动完成的工作: - 在 Xcode 中创建 tvOS 目标(File > New > Target > tvOS App) - 将新目标添加到 Xcode 项目(.pbxproj 修改) - 为 TV 目标配置 App Groups 权益 - 将 TV 目标添加到现有 scheme 或创建新 scheme - 手动将 Agent 创建的所有 Swift 文件添加到 TV 目标 - 手动测试 Siri Remote 导航(Agent 无法评估焦点行为)
结果:15 个新的 Swift 文件,功能完整的 TV 应用,Agent 辅助工作约 3 小时。据我估计,Agent 处理了大约 80% 的实现工作;我处理了需要 Xcode UI 交互的部分(权益、目标设置、能力标志)以及在真实 Apple TV 上的手动焦点测试。基于我在没有 Agent 的情况下交付过的类似功能,在该代码库中独自完成同等工作量需要数天时间。
案例研究 2:amp97 中的 Metal 着色器调试(部分失败)
任务:为示波器着色器添加基于能量的强度系统。可视化效果应随音频能量脉动。
发生了什么:
1. Agent 编写了一段有效的 Metal 着色器修改,添加了 uEnergy uniform 和 HDR 色调映射
2. 代码编译没有错误
3. 在设备上,可视化完全是白色——强度系数高了 10 倍(3.5 而非 0.30)
4. Agent 看不到白屏,因此没有反馈信号
5. 我通过视觉识别问题,并要求 Agent 减小系数
6. Agent 减小了系数,但整体能量状态机过于复杂,以不同方式破坏了可视化器
7. 完全回滚——两次提交(67959ed 和 cda4830)在 869d914 中被回滚
经验教训:Metal 着色器是 Agent 辅助开发中最棘手的领域,因为反馈循环是断裂的。Agent 可以验证语法(能编译)和语义(类型正确),但无法验证输出(看起来对)。任何会改变视觉行为的着色器修改都需要在设备上由人工验证。
事后我添加到 CLAUDE.md 的内容:“在没有极其谨慎的系数测试的情况下,不要尝试对示波器着色器进行能量状态修改。先前的尝试因系数高了 10 倍而破坏了可视化器。”
案例研究 3:Banana List 中的 SwiftData 迁移(成功)
任务:将数据模型从 V1 迁移到 V2,为 GroceryItem 添加 quantity 字段,并新增带关系的 Category 模型。
Agent 做了什么:
1. 阅读了现有的 V1 模型定义
2. 创建了带有新字段和关系的 V2 模型定义
3. 编写了符合 SchemaMigrationPlan 协议的 GroceryMigrationPlan
4. 实现了 V1toV2 迁移阶段:添加默认值 quantity: 1 和 category: nil
5. 更新了所有视图以支持新字段
6. 更新了 SampleData.swift 用于预览
7. 通过 MCP 构建并运行测试——全部通过
8. 创建了迁移专用的单元测试
关键:Agent 之所以成功,是因为 SwiftData 迁移遵循一种定义良好的协议模式,该模式在 Apple 的文档和训练数据中都有充分体现。CLAUDE.md 明确记录了 V1 模型,因此 Agent 理解它要从什么迁移而来。
案例研究 4:Return 中的 iCloud 会话同步(成功但具有复杂性)
任务:实现跨设备冥想会话日志记录。在 Apple TV 或 Mac 上完成的会话应同步到 iPhone 进行 HealthKit 记录。
Agent 产出的成果:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ tvOS │ │ Mac │ │ Watch │
│ TVTimerMgr │ │ TimerMgr │ │ WatchTimer │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────────┼───────────────────┘
│
▼
┌────────────────────────┐
│ SessionStore │
│ (iCloud Key-Value) │
└───────────┬────────────┘
│
▼
┌────────────────────────┐
│ iPhone (on foreground)│
│ → Write to HealthKit │
└────────────────────────┘
Agent:
1. 创建了 MeditationSession 数据模型,包含 UUID、日期、时长、来源设备和 HealthKit 同步状态
2. 构建了管理 NSUbiquitousKeyValueStore 用于 iCloud 同步的 SessionStore 单例
3. 实现了合并冲突解决(基于 UUID 的去重)
4. 添加了 SessionHistoryView,带有特定平台的适配(iOS 上的滑动删除,tvOS 上的基于焦点的操作)
5. 接通了 iPhone 端针对来自其他设备会话的 HealthKit 同步
需要迭代的部分:初始实现没有处理 iPhone 应用在后台启动的情况(没有用于同步的前台通知)。Agent 需要具体的指导:”使用 NSUbiquitousKeyValueStore.didChangeExternallyNotification 在后台 KV 变更时触发同步。”得到这个提示后,实现就正确了。
经验教训:当架构被清晰描述时,Agent 能够很好地处理多平台架构模式。iCloud 同步模式并不简单,但它遵循 Agent 能够理解的、有文档记录的 Apple 模式。边缘情况(后台同步)需要人类的领域知识,因为它没有得到充分的文档说明。
案例研究 5:Starfield Destroyer 中的 Game Center 集成(成功)
任务:为太空射击游戏添加 Game Center 排行榜和成就。
Agent 做得好的地方:
- 在应用入口点实现了 GKLocalPlayer.local.authenticateHandler
- 创建了带有分数提交和成就上报方法的 GameCenterManager
- 在所有 Game Center 操作之前添加了认证状态检查
- 优雅地处理了离线情况(游戏可以在没有 Game Center 的情况下进行,重新连接时再提交)
- 创建了与 8 艘飞船进阶系统相匹配的成就定义
需要手动完成的工作: - 在 App Store Connect 中创建排行榜和成就(网页门户,Agent 无法访问) - 在 Xcode 中配置 Game Center 权益 - 使用沙盒 Game Center 账户进行测试(需要在设备上手动登录)
项目生命周期与智能体
启动新的iOS项目
借助智能体启动新项目的最佳工作流程:
阶段1:人工设置(15-30分钟) 1. 创建Xcode项目(File > New > Project) 2. 配置签名和功能权限 3. 设置部署目标和支持的目标设备 4. 添加所需的entitlements(HealthKit、Game Center等) 5. 创建包含项目身份和规则的初始CLAUDE.md
阶段2:智能体实现(数小时至数天) 1. 智能体创建数据模型(SwiftData、Core Data或普通struct) 2. 智能体根据您记录的模式构建视图 3. 智能体在manager/service类中实现业务逻辑 4. 智能体编写单元测试 5. 通过MCP进行构建-测试-修复循环(自主进行)
阶段3:人工集成(30-60分钟) 1. 将智能体创建的文件添加到Xcode targets 2. 验证签名和entitlements 3. 在物理设备上测试 4. 审查视觉布局和UX 5. 提交到App Store Connect
维护现有项目
针对成熟应用的持续开发:
You: Here's the next feature for Return: add a "Focus Score" that
calculates from session duration and consistency. Show it on
the main timer view. Build and test.
Claude: [reads CLAUDE.md, understands patterns]
[reads TimerManager.swift, Settings.swift]
[creates FocusScore.swift — model with calculation logic]
[creates FocusScoreView.swift — display component]
[integrates into ContentView.swift]
[calls build_sim — 1 error: missing import]
[fixes import]
[calls build_sim — success]
[writes FocusScoreTests.swift]
[calls test_sim — all pass]
智能体的有效性取决于您的CLAUDE.md对项目当前状态的反映程度。当您添加重要的新功能、变更架构模式或引入新框架时,请及时更新CLAUDE.md。
何时让智能体介入,何时不该介入
| 任务 | 是否使用智能体? | 原因 |
|---|---|---|
| 新建SwiftUI视图 | 是 | 智能体擅长声明式UI |
| SwiftData模型变更 | 是 | 定义清晰、可测试 |
| 单元测试 | 是 | 机械化、基于模式 |
| 重构 | 是 | 系统化、跨文件 |
| 构建错误诊断 | 是(通过MCP) | 结构化反馈循环 |
| 新建Xcode target | 否 | 需要Xcode UI、变更.pbxproj |
| 签名与配置文件 | 否 | 基于Portal,智能体无法访问 |
| 视觉打磨 | 否 | 需要人类审美判断 |
| Metal着色器调优 | 否 | 需要在设备GPU上测试 |
| App Store提交 | 否 | 需要Portal和Xcode Organizer |
| 性能剖析 | 否 | 需要Instruments |
| 无障碍审计 | 部分 | 智能体可添加标签,由人验证VoiceOver |
配置智能体定义
如果您使用Claude Code的智能体定义系统(.claude/agents/),可创建一个iOS专属智能体:
---
name: ios-developer
description: iOS development agent with MCP build tools and SwiftUI expertise
tools:
- XcodeBuildMCP
- xcode
---
# iOS Developer Agent
You are an iOS development agent for apps targeting iOS 26+ with SwiftUI.
## Architecture Rules
- @Observable for all view models (NEVER ObservableObject)
- NavigationStack for all navigation (NEVER NavigationView)
- SwiftData for persistence
- Swift 6.2 strict concurrency
- @MainActor on all Observable classes
## Build & Test — Always Use MCP
Prefer MCP tools over raw shell commands for ALL build operations:
- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim`
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)
MCP returns structured JSON. Bash returns unstructured text.
## File Management Rules
- NEVER modify .pbxproj, .xcodeproj/, .xcworkspace/, .xib, .storyboard
- Create Swift files in the correct directory
- Report files that need manual addition to Xcode targets
## SwiftData Rules
- @Model classes are automatically Observable — do not add @Observable
- Use @Bindable for form bindings to model properties
- Use @Query in views, modelContext.fetch() elsewhere
- Document relationship delete rules
## When You Get Stuck
- Build errors: use `build_sim` via MCP for structured output
- API questions: use `DocumentationSearch` via Apple MCP
- Swift verification: use `ExecuteSnippet` via Apple MCP
- Never guess — verify with tools
在Claude Code会话中通过@ios-developer引用此智能体。
智能体辅助iOS开发的测试模式
只要给予明确的指引,智能体便能写出优秀的单元测试。以下是可产出最佳成果的模式。
测试文件组织
# In CLAUDE.md:
## Test Structure
Tests mirror source structure:
- `ReturnTests/TimerManagerTests.swift` tests `TimerManager.swift`
- `ReturnTests/SettingsTests.swift` tests `Settings.swift`
- `ReturnTests/ConstantsTests.swift` tests `Constants.swift`
Test naming: `test_<what>_<condition>_<expected>`
Example: `test_start_whenStopped_transitionsToRunning`
编写测试的提示
有效的测试提示:
Write unit tests for TimerManager covering:
1. Initial state is .stopped with timeRemaining == selectedDuration
2. start() transitions state to .running
3. pause() from .running transitions to .paused
4. reset() from any state returns to .stopped with original duration
5. start() from .paused resumes (state becomes .running)
6. Edge case: reset() when already stopped is a no-op
7. Edge case: pause() when already paused is a no-op
Follow the existing test pattern in SettingsTests.swift.
Use setUp() to create a fresh TimerManager for each test.
为何有效: 编号的验收标准为智能体提供了清晰的检查清单。引用现有测试文件可确立模式范本。明确指定使用setUp()可避免智能体写出纠缠不清的测试状态。
无效的测试提示:
Write tests for TimerManager.
这只会产出泛泛而谈、流于表面的测试,遗漏边界情况,也未必符合项目的既有模式。
异步测试模式
测试基于计时器和异步的代码时:
// Agent produces this pattern when guided correctly:
final class TimerManagerTests: XCTestCase {
var sut: TimerManager!
@MainActor
override func setUp() {
super.setUp()
sut = TimerManager()
}
@MainActor
func test_start_whenStopped_transitionsToRunning() {
// Given
XCTAssertEqual(sut.state, .stopped)
// When
sut.start()
// Then
XCTAssertEqual(sut.state, .running)
}
@MainActor
func test_timerCountsDown_afterOneSecond() async throws {
// Given
sut.selectedDuration = 10
sut.reset()
sut.start()
// When
try await Task.sleep(for: .seconds(1.1))
// Then
XCTAssertLessThanOrEqual(sut.timeRemaining, 9.0)
}
}
智能体需要被反复提醒的关键模式:
- 在测试@MainActor类的方法上加@MainActor
- 使用Task.sleep或异步操作的测试需声明async throws
- 时间相关断言要留有容差(1.1秒,而非精确的1.0)
- 使用干净的setUp() / tearDown()保证测试隔离
快照测试
如需视觉回归检测,可考虑引入swift-snapshot-testing:
Add snapshot tests for the main timer view in three states:
1. Stopped (showing full duration)
2. Running (showing countdown)
3. Completed (showing 00:00 with completion state)
Use SnapshotTesting library. Create reference images on first run.
智能体能够正确地搭建快照测试框架,但无法审查参考图片本身。您审查首次生成的快照后,智能体编写的测试便能在后续变更中自动捕捉视觉回归。
iOS项目的上下文窗口管理
1M上下文窗口(Opus 4.6)虽然很大,但并非无限。iOS项目有特定的上下文管理考量。
iOS文件的Token成本
| 文件类型 | 典型大小 | 大致Token数 |
|---|---|---|
| SwiftUI视图(简单) | 50-100行 | 500-1,000 |
| SwiftUI视图(复杂) | 200-400行 | 2,000-4,000 |
| SwiftData模型 | 30-80行 | 300-800 |
| Manager/服务类 | 100-300行 | 1,000-3,000 |
| Metal着色器(.metal) | 50-200行 | 500-2,000 |
| 单元测试文件 | 50-200行 | 500-2,000 |
| CLAUDE.md | 100-300行 | 1,000-3,000 |
| MCP响应(构建) | 不定 | 200-2,000 |
| MCP响应(测试) | 不定 | 500-5,000 |
对于50个文件的项目:读取所有文件大约消耗50,000-100,000个token——完全在1M窗口范围内。Agent可以将整个项目保留在上下文中。
对于100+文件的项目:选择性读取变得必要。Agent首先读取CLAUDE.md(获取文件结构注释),然后根据需要读取特定文件。这就是为什么CLAUDE.md中的文件注释至关重要——它们引导Agent找到正确的文件,而无需读取所有内容。
大型项目的策略
- 详细的CLAUDE.md文件注释——Agent读取文件映射并直接导航到相关文件
- 子Agent委派——将探索和研究路由到子Agent(干净的上下文,返回摘要)
- 聚焦的提示词——“修改SettingsView.swift以添加一个新开关”比”更新设置”更好
- 会话边界——为不相关的功能启动新会话,而不是延长一个长会话
- 使用
/compact——Claude Code的压缩命令会总结对话并释放上下文
MCP Token效率
支持MCP的最有力论据之一:结构化的JSON响应消耗的token远少于原始的xcodebuild输出。
| 场景 | 原始Bash Token | MCP Token | 节省 |
|---|---|---|---|
| 成功构建 | 3,000-10,000 | 200-500 | 85-95% |
| 失败构建(1个错误) | 3,000-10,000 | 300-800 | 90-92% |
| 测试结果(20个测试) | 2,000-5,000 | 500-1,000 | 75-80% |
| 模拟器列表 | 500-2,000 | 200-400 | 60-80% |
在一个有10-20次构建周期的典型开发会话中,MCP相比原始xcodebuild节省了30,000-150,000个token——这些token可用于实际的代码推理。
故障排查
“build_sim failed — scheme not found”
Agent在猜测scheme名称。修复方法:
Use discover_projs and list_schemes to find the correct scheme name
for this project before building.
或者将scheme名称显式添加到您的CLAUDE.md中:
## Build
Primary scheme: `Return` (iOS)
Watch scheme: `ReturnWatch` (watchOS)
TV scheme: `ReturnTV` (tvOS)
“xcrun mcpbridge — command not found”
您需要Xcode 26.3或更高版本。使用xcodebuild -version检查。如果您已经有Xcode 26.3+但命令仍然失败:
# Ensure Xcode command line tools are selected
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
# Verify
xcrun mcpbridge --help
“MCP工具未在Claude Code中出现”
会话中途注册的MCP工具可能要等到重启后才会出现。退出Claude Code并启动新会话:
# Exit current session (Ctrl+C or /exit)
# Start fresh
claude
然后验证:
You: List all available MCP tools from XcodeBuildMCP.
“Agent持续通过Bash使用xcodebuild,而不是MCP”
Agent没有通过Tool Search发现MCP工具。两种修复方法:
- 在CLAUDE.md中添加显式指引(参见教Agent使用MCP)
- 直接提示:“使用build_sim MCP工具,而不是通过Bash调用xcodebuild”
“构建成功但Agent报告失败”
XcodeBuildMCP解析xcodebuild输出。如果构建产生看起来像错误的警告(常见于弃用警告),Agent可能会误解结果。请检查MCP响应中实际的状态字段。
“模拟器在启动时挂起”
终止所有模拟器并重启:
xcrun simctl shutdown all
xcrun simctl boot "iPhone 16 Pro"
或者请求Agent:
Shut down all simulators, then boot a fresh iPhone 16 Pro.
“尽管有CLAUDE.md规则,Agent仍尝试修改.pbxproj”
CLAUDE.md规则只是建议。Hooks才是强制执行机制。如果您没有PreToolUse hook阻止.pbxproj写入,Agent最终会尝试这样做。安装hook:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files.\" >&2; exit 2; fi'"
}
]
}
}
规则说”请不要”。Hooks说”你不能”。
常见问题
我应该从哪个Agent运行时开始?
带XcodeBuildMCP的Claude Code CLI。它拥有最深度的MCP集成、最成熟的hook系统,以及能够将整个iOS项目保留在工作内存中的1M上下文窗口(Opus 4.6)。从这里开始,然后随着工作流程的成熟,添加Codex用于审查,Xcode原生agent用于快速内联编辑。
我需要两个MCP服务器吗?
对于大多数开发者来说,仅XcodeBuildMCP就能满足90%的需求(构建、测试、模拟器、调试)。如果您需要文档搜索、Swift REPL验证或SwiftUI预览渲染,请添加Apple的Xcode MCP。您可以随时添加——两个服务器是独立的。
Agent能从零创建一个新的Xcode项目吗?
XcodeBuildMCP包含一个create_project工具,可以搭建新的Xcode项目。然而,对于生产应用,建议在Xcode中创建项目(以正确获取签名、capabilities和target配置),然后使用agent进行所有代码实现。您在Xcode新项目向导中花费的5分钟,可以省下数小时排查agent生成的项目配置问题。
Agent如何处理Swift Package Manager依赖?
处理得很好。Package.swift是一个标准的Swift文件,agent可以可靠地读取和编辑。添加依赖、更新版本范围以及配置targets都能正常工作。限制在于基于.xcodeproj的依赖管理(Xcode的package解析UI)——这部分由Xcode管理,不应由agent编辑。
Agent能提交到App Store吗?
不能。App Store提交涉及Xcode的Organizer、provisioning profiles、截图、元数据以及App Store Connect门户。这些都无法通过MCP或命令行工具以agent能够有意义地操作的方式访问。Agent处理直至归档之前的所有事项——实现、测试、bug修复和文档编写。提交的最后一英里仍由人工操作。
不过,agent可以协助处理App Store元数据。请agent根据最新更改撰写应用描述、关键词和”新功能”文本。这是agent擅长的文本生成工作。
在agent辅助的iOS开发中,如何处理secrets和API密钥?
切勿提交secrets。对于连接后端API的iOS应用:
- 使用
.xcconfig文件进行环境特定配置 - 将
.xcconfig文件添加到.gitignore - 通过
Info.plist构建设置引用配置值 - 在CLAUDE.md中记录所需的secrets,但不包含实际值
## Configuration
API base URL and keys are in `Config.xcconfig` (not committed).
Required keys:
- `API_BASE_URL` — Backend server URL
- `API_KEY` — Authentication token
Create `Config.xcconfig` from `Config.xcconfig.template`.
Agent知道这些密钥存在以及它们的使用位置,但永远看不到实际值。
SwiftUI动画呢——agent能写吗?
Agent能在语法层面正确编写动画代码,但无法在视觉上验证结果。简单动画(.animation(.spring())、.transition(.slide)、withAnimation { })能产生正确结果。带有精确时序的复杂多步动画需要视觉迭代,这是agent无法做到的。
有效:“在计时器在状态间过渡时添加spring动画。”
无效:“让计时器动画感觉令人满意。”(主观,需要视觉调整。)
Agent如何处理错误处理模式?
非常好。Agent理解Swift的do/catch、Result和async throws模式:
Implement error handling for the HealthKit authorization flow:
1. Check HKHealthStore.isHealthDataAvailable() — show alert if not
2. Request authorization — handle denial gracefully
3. On write failure — retry once, then show error
4. All errors should be user-facing with localized descriptions
Agent能产出带有适当面向用户消息的结构化错误处理。它们有时会过度处理错误(捕获本应传播的异常),因此请审查catch块。
我可以使用agent进行无障碍功能实现吗?
部分可以。Agent能正确添加accessibility标签、提示和特征:
Add accessibility labels to all interactive elements in TimerView:
- Timer display: current time remaining
- Start/Pause button: current state and action
- Reset button: "Reset timer"
- Duration picker: selected duration
Agent无法做到的:验证VoiceOver导航顺序是否正确、测试Dynamic Type缩放,或评估颜色对比度。请使用Xcode的Accessibility Inspector进行验证。
Agent如何处理Core Data迁移(如果不使用SwiftData)?
Agent能编写Core Data迁移映射和模型版本,但手动的Xcode步骤(创建新模型版本、选择当前版本)无法自动化。如果您仍在使用Core Data而非SwiftData,请在CLAUDE.md中记录模型版本历史:
## Core Data模型版本
- V1:初始版本(GroceryList、GroceryItem)
- V2:新增Category模型(当前版本)
- 迁移:V1→V2采用轻量级自动迁移
智能体如何处理SwiftUI预览?
有两种方式:
1. Apple Xcode MCP的RenderPreview工具以无头模式渲染预览并返回结果。智能体可以验证预览是否能够编译并无错误地渲染,但无法评估视觉正确性。
2. 基于构建的验证通过build_sim确认预览提供器能够编译。如果预览在运行时崩溃,构建仍会成功——崩溃只会在Xcode尝试渲染预览时显现。
如需对预览进行视觉验证,仍需打开Xcode。
visionOS和Apple Vision Pro呢?
适用相同的模式。XcodeBuildMCP支持visionOS模拟器,且架构模式(@Observable、NavigationStack、SwiftData)完全相同。RealityKit专属代码(3D内容、沉浸式空间、手部追踪)遵循与Metal相同的限制——智能体可以编写正确的代码,但无法验证空间输出。
项目规模达到多大时智能体会力不从心?
上下文窗口大小是限制因素。借助Opus 4.6的1M token窗口,Claude Code可以同时在活跃工作内存中容纳大约50-70个Swift文件。对于更大的项目,智能体会使用文件搜索和选择性读取来处理代码库的子集。包含100+文件的项目运行良好——智能体只需按需读取文件,而非将所有内容保留在上下文中。
实际限制并非文件数量,而是代码库的连贯性。一个文档完善、配有详细CLAUDE.md的200文件项目,会比一个无文档的30文件项目产出更好的结果。
使用智能体进行iOS开发是否需要懂Swift?
您需要能够审查智能体的输出并做出架构决策。您不必亲自编写每一行代码,但需要充分理解Swift,以便在智能体做出错误选择时能够察觉——尤其是涉及并发、内存管理和框架专属模式时。智能体是您现有技能的10倍放大器,而非替代品。
智能体如何处理Swift文件中的合并冲突?
智能体能够可靠地解决Swift源文件中的合并冲突。所有智能体运行时都能很好地理解标准冲突标记(<<<<<<<、=======、>>>>>>>)。然而,.pbxproj文件中的合并冲突仍是手动解决的任务——不要让智能体解决.pbxproj冲突。
运行智能体进行iOS开发的成本是多少?
使用Anthropic的Max套餐(Opus 4.6,1M上下文),一次典型的iOS开发会话持续30-120分钟,处理200K-800K个token。MCP工具调用增加的开销极小(结构化的JSON响应相比原始构建输出更节省token)。其成本与在任何其他代码库上运行Claude Code相当——iOS开发并不比Web开发明显更贵或更便宜。
我可以将智能体用于UIKit项目吗?
可以,但智能体在SwiftUI上更有效。UIKit需要更多样板代码,声明式结构较少,且通常涉及智能体无法编辑的Interface Builder文件。如果您有UIKit项目,可以考虑让智能体处理模型层和业务逻辑,而手动处理UI,或者逐步将视图迁移到SwiftUI。
智能体如何处理本地化?
智能体能有效地创建和编辑.xcstrings(Xcode字符串目录)文件。它们可以添加新的本地化键、提供翻译,并在多种语言之间保持一致性。.xcstrings文件的结构化JSON格式对智能体非常友好。对于.strings文件(旧版格式),智能体同样表现良好——其键值对格式十分直接。
iOS中常见的智能体错误(及预防方法)
这些是我在8个iOS项目的数千次智能体交互中观察到的反复出现的错误。每种错误都有相应的预防策略。
错误1:混用Observable模式
现象: 智能体在一个文件中使用@Observable,在另一个文件中使用ObservableObject,或者将@Observable添加到@Model类(该类已经是Observable)。
预防: 在CLAUDE.md中明确规则:
- NEVER use ObservableObject — use @Observable
- NEVER add @Observable to @Model classes (already Observable)
- NEVER use @StateObject — use @State with @Observable
- NEVER use @ObservedObject — access @Observable properties directly
错误2:在闭包中创建循环引用
现象: 智能体创建的闭包强引用self,尤其是在Timer.publish、NotificationCenter和完成处理器中。
预防: 在CLAUDE.md中包含闭包模式:
## Closure Pattern
- Timer callbacks: use `[weak self]` and guard
- NotificationCenter observers: store in `Set<AnyCancellable>` and use `[weak self]`
- Completion handlers: use `[weak self]` for any closure stored beyond the call site
错误3:忽略@MainActor要求
现象: 智能体创建@Observable类时未使用@MainActor隔离,导致Swift 6.2并发警告,或在UI更新发生在非主线程时引发运行时崩溃。
预防:
## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
```swift
@Observable
@MainActor
final class SomeManager { }
```
错误4:使用带Destination闭包的NavigationLink
现象: 智能体使用已弃用的NavigationLink(destination:label:),而非类型安全的NavigationLink(value:) + .navigationDestination(for:)模式。
预防:
## Navigation Pattern
ALWAYS use value-based navigation:
```swift
NavigationLink(value: item) { ItemRow(item: item) }
.navigationDestination(for: Item.self) { ItemDetailView(item: $0) }
```
NEVER use: `NavigationLink(destination: ItemDetailView(item: item)) { }`
错误5:硬编码模拟器名称
现象: 智能体编写带有特定模拟器名称(”iPhone 16 Pro”)的构建命令,而这些设备可能在您的系统上并不存在。
预防: MCP可处理此问题——list_sims可发现可用模拟器。在CLAUDE.md中:
## Simulators
Do NOT hardcode simulator names. Use `list_sims` MCP tool to discover
available devices, then `boot_sim` with the discovered device ID.
错误6:在错误的目录中创建文件
现象: 智能体在项目根目录而非Views/子目录中创建新视图文件,或将模型放入错误的分组。
预防: CLAUDE.md中的文件结构注释可指导文件放置。此外:
## File Placement Rules
- Views → `AppName/Views/`
- Models → `AppName/Models/`
- Managers → `AppName/Managers/`
- Extensions → `AppName/Extensions/`
- Tests → `AppNameTests/`
错误7:未处理平台可用性
现象: 智能体在为tvOS(HealthKit不可用)编译的共享代码中使用HealthKit,或在watchOS代码中使用ActivityKit。
预防:
## Platform Guards
- HealthKit: `#if canImport(HealthKit)` (unavailable on tvOS)
- ActivityKit: `#if canImport(ActivityKit)` (iOS only)
- WatchKit: `#if os(watchOS)`
- UIKit haptics: `#if os(iOS)` (unavailable on tvOS, watchOS uses WKHaptic)
错误8:对简单功能过度设计
现象: 智能体为本应是20行实用函数的需求创建了协议、协议扩展、具体实现、工厂和依赖注入容器。
预防: 包含简洁性原则:
## Architecture Principle
Prefer the simplest solution that handles the requirements.
- Direct implementation over protocol abstraction (unless you have 2+ conforming types)
- Concrete types over generics (unless reuse is proven)
- Extensions on existing types over new wrapper types
诚实的评估
在使用AI智能体交付了8款iOS应用之后,以下是总结:
智能体改变了什么: 实现速度。原本需要数天的工作现在只需数小时。SwiftUI视图、SwiftData模型、单元测试、重构——这些现在主要由智能体生成、人类审查。
智能体没有改变什么: 架构决策、视觉设计、性能优化或App Store提交。这些仍由人类主导。
倍增效应真实存在但有边界。 我对8款应用组合的主观估计:在文档完善、配备适当MCP和钩子配置的项目上,功能交付时间提升3至5倍。这不是与对照组的对比测量;而是同一代码库中智能体辅助功能与等效独立工作的实际耗时对比。无文档、无钩子的项目大约只有1.5至2倍的提升——智能体花费过多时间在猜测而非构建上。18
真正有回报的投入: 在CLAUDE.md、钩子和MCP配置上花费的时间。每一小时的设置都能节省大量纠正智能体错误的时间。配置即产品——智能体只是执行引擎。
令我感到意外的: MCP服务器对工作动态的改变之大。在MCP出现之前,智能体只是恰好懂Swift的高级文本编辑器。有了MCP之后,它们成为能编写、构建、测试、调试和迭代的开发伙伴。结构化的反馈循环正是”编写代码的智能体”与”交付代码的智能体”之间的分水岭。
我会告诉过去的自己什么: 从最小的应用开始(Reps,14个文件),把MCP和钩子配置做对,写一份完善的CLAUDE.md,然后将这些模式推广到更大的项目。不要从63个文件的多平台应用入手。无论项目规模如何,基础设施投入都相同——在小项目上做一次,然后复制到其他所有项目。
未来: Xcode 26.3的原生智能体集成是开始,而非结束。Apple支持MCP意味着工具链正在向智能体优先的开发模式演进。现在投资于智能体兼容项目结构的开发者——干净的CLAUDE.md文件、可测试的架构、自动化钩子——将随着工具的改进而获得复利回报。
速查卡
安装(一次性设置)
# XcodeBuildMCP (59 tools)
claude mcp add XcodeBuildMCP -s user \
-e XCODEBUILDMCP_SENTRY_DISABLED=true \
-- npx -y xcodebuildmcp@latest mcp
# Apple Xcode MCP (20 tools)
claude mcp add --transport stdio xcode -s user -- xcrun mcpbridge
# Codex MCP setup
codex mcp add xcode -- xcrun mcpbridge
# Verify
claude mcp list
必备的CLAUDE.md章节
1. Project identity (bundle ID, target OS, architecture)
2. File structure with annotations
3. Build and test commands
4. Key patterns and rules
5. Prohibitions (NEVER touch .pbxproj)
6. Framework-specific context
必备的钩子
{
"PreToolUse": [{ "matcher": "Edit|Write", "command": "block .pbxproj" }],
"PostToolUse": [{ "matcher": "Edit|Write", "command": "swiftformat" }]
}
架构规则
@Observable (not ObservableObject)
NavigationStack (not NavigationView)
@State (not @StateObject)
SwiftData @Model (not Core Data)
async/await (not completion handlers)
@MainActor (on all Observable classes)
.glassEffect() (Liquid Glass, iOS 26+)
MCP工具优先级
Build: build_sim (not xcodebuild via Bash)
Test: test_sim (not xcodebuild test via Bash)
Sim: list_sims/boot_sim (not xcrun simctl via Bash)
Docs: DocumentationSearch (not WebSearch)
REPL: ExecuteSnippet (not swift via Bash)
变更日志
| 日期 | 变更内容 |
|---|---|
| 2026-04-28 | 将智能体工作流推荐的Xcode版本提升至26.4+(26.4.1于2026-04-16发布,版本号17E202,为最新稳定版,仅含错误修复)。引用了对智能体编写测试和本地化有用的Xcode 26.4特性(2026-03-24发布,版本号17E192):Swift Testing图像附件、Issue.record的严重性参数、带附加崩溃日志的UI测试崩溃警告(专门针对XCUIApplication(bundleIdentifier:)/XCUIApplication(url:)类应用)、String Catalog编辑器改进。添加了xcodebuildmcp init自动安装器(v2.1.0+,2026-02-23),作为手动MCP设置的替代方案。 |
| 2026-04-27 | App Store Connect:从2026-04-28起强制要求使用Xcode 26+提交。Foundation Models新增SystemLanguageModel.contextSize和tokenCount(for:) API(回溯部署至iOS 26.4)——添加了一个用于智能体生成FM提示预算代码的模式。iOS 26.4.2(4月22日)和iOS 26.5 beta 3(4月20日)发布,未涉及影响智能体工具链的变更。 |
| 2026-04-13 | 首次发布。8款应用、3种运行时、MCP设置、CLAUDE.md模式、钩子、案例研究。 |
参考资料
-
XcodeBuildMCP默认包含Sentry遥测。该项目的隐私文档详细说明了发送的内容:错误消息、堆栈跟踪,以及在某些情况下的文件路径。
XCODEBUILDMCP_SENTRY_DISABLED=true环境变量可完全退出。 ↩ -
Anthropic,”Model Context Protocol Specification”,modelcontextprotocol.io/specification。MCP规范定义了JSON-RPC传输、工具发现和资源协议,XcodeBuildMCP与Apple的Xcode MCP均依此实现。 ↩
-
XcodeBuildMCP,github.com/getsentry/XcodeBuildMCP。开源项目,由Sentry维护。涵盖模拟器、设备、调试和UI自动化工作流的59个工具。采用语义化版本管理,并附有变更日志。 ↩
-
Apple在Xcode 26.3智能开发者工具计划中引入了Xcode MCP服务器,将MCP定位为AI编程助手与Xcode工具链之间的接口层。官方文档请参阅Xcode Release Notes。 ↩
-
Rudrank Riyam,”Exploring Xcode Using MCP Tools”,rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients,2026年。独立验证了Apple的MCP工具数量、XPC依赖以及文档搜索能力。 ↩
-
Jimenez, C.E., Yang, J., Wettig, A., 等,”SWE-bench: Can Language Models Resolve Real-World GitHub Issues?”,ICLR 2024。arxiv.org/abs/2310.06770。具备结构化工具访问能力的智能体,显著优于仅限非结构化Shell命令的智能体。该结论印证了结构化MCP接口对智能体效能的提升作用。 ↩
-
Claude Code CLI文档,code.claude.com。涵盖钩子系统、MCP配置、子智能体委派以及智能体定义。 ↩
-
SwiftFormat,github.com/nicklockwood/SwiftFormat。在PostToolUse钩子中使用的Swift格式化工具,用于保持代码风格一致。 ↩
-
XcodeBuildMCP官方网站,xcodebuildmcp.com。通过CLI输出示例确认共有59个MCP工具。工具类别包括:模拟器、设备、调试和UI自动化。可通过Homebrew或npx安装。 ↩
-
Swiftjective-C,”Agentic Coding in Xcode 26.3 with Claude Code and Codex”,swiftjectivec.com,2026年2月。确认Xcode 26.3通过Settings > Intelligence原生支持Claude Agent和Codex运行时。通过
xcrun mcpbridge暴露20个MCP工具。 ↩ -
Blake Crosley,”Two MCP Servers Made Claude Code an iOS Build System”,blakecrosley.com/blog/xcode-mcp-claude-code,2026年2月。同一作者在iOS开发工作流中的配置流程及实际成果。 ↩
-
Apple开发者新闻,“Upcoming Requirements”。2026-04-28的条目:”上传至App Store Connect的应用必须使用Xcode 26或更高版本,并基于面向iOS 26、iPadOS 26、tvOS 26、visionOS 26或watchOS 26的SDK构建。”该要求所列平台不包括macOS。 ↩
-
Apple,“Xcode 26.4 Release Notes”。Xcode 26.4(2026-03-24,构建版本17E192)。发布说明中引用的特性包括:Swift Testing现支持通过
CGImage、NSImage、UIImage和CIImage附加图像;Issue.record接受严重级别参数;部分UI测试中应用崩溃——特别是通过XCUIApplication(bundleIdentifier:)或XCUIApplication(url:)交互的应用——会以警告形式报告并附带崩溃日志,而非导致测试失败;String Catalog编辑器新增了条目的剪切/复制/粘贴、语言移除以及从现有语言预填翻译功能,并新增了BUILD_ONLY_KNOWN_LOCALIZATIONS设置。 ↩ -
Apple开发者新闻,“Xcode 26.4.1 (Build 17E202) Now Available”,2026-04-16。仅为缺陷修复的小版本更新——修复了iOS / macOS / visionOS 26.4之前版本中因符号缺失导致的MetricKit崩溃,以及Swift异步栈分配缺陷(
swift_asyncLet_finish中的”freed pointer was not the last allocation”)。 ↩ -
getsentry/XcodeBuildMCP v2.1.0版本,2026-02-23。新增
xcodebuildmcp initCLI命令,可一步完成智能体技能与MCP配置的安装,取代了独立的install-skill.sh脚本。自动检测Claude Code、Cursor和Codex;支持--print(将配置输出至stdout,适用于不受支持的客户端)和--uninstall(卸载)。 ↩ -
InfoQ,“Apple Adds Context Window Management to Foundation Models”,2026年3月。记录了新增的
SystemLanguageModel.contextSize和tokenCount(for:)API,并确认了@backDeployed(before: iOS 26.4)注解。取代了此前社区对4096-token硬编码的猜测。 ↩ -
文件数量基于2026-04-27对8个私有应用仓库分别运行
find . -name '*.swift' -not -path '*/Tests/*' | wc -l所得。已排除测试文件。总数与§The Portfolio中各应用明细表保持内部一致。 ↩ -
主观估算的实际耗时,并非对照组测量结果。3-5倍的数据来源于作者对2026年智能体辅助开发的功能与此前在相同代码库中独立完成的等效功能之间的耗时回忆。请将其视为完成MCP与钩子配置后的预期启发参考,而非基准测试结果。 ↩