
之前在做 App 原型时最耗时间的往往不是想法本身而是把想法变成屏幕上的效果手绘线框图不够直观用 Axure 或 Sketch 搭建又需要额外学习成本和开发实际用的 SwiftUI 代码还经常是两套东西。后来发现 Xcode 内置的智能体Agent可以直接根据自然语言生成 SwiftUI 界面并能读取、修改工程文件这让“从一句话到一份可点击原型”变成了几分钟内的事。这篇文章就把我用Xcode 智能体创建 UI 原型的完整过程整理出来包含环境要求、核心概念、完整实战案例、常见报错排查和工程落地建议适合 iOS 开发者、独立开发者和正在尝试 AI 辅助设计的产品同学阅读。1. Xcode 智能体与 UI 原型的基础概念1.1 什么是 Xcode 智能体Xcode 26 引入的智能体Agent可以理解为 Xcode 内置的 AI 编程助手但它和普通的代码补全、代码聊天工具不同它能被授予操作当前工程的权限执行类似开发者的操作读取文件内容、修改 Swift 文件、创建新文件、运行命令、检查编译报错等。从交互方式上讲智能体更像一个住在 Xcode 里的结对程序员你能用自然语言描述需求比如“帮我在 ContentView 里加一个底部 Tab 栏”。它会基于当前工程上下文自己决定修改哪些文件、怎么写代码。修改完成后你可以直接在 Xcode 里查看差异、运行验证效果。如果把它应用在 UI 原型设计上核心价值就很明显你不再需要在设计工具和开发工具之间来回切换原型直接用 SwiftUI 生成天然和工程代码同源。1.2 为什么用智能体生成 UI 原型传统的 UI 原型制作方式有很多比如 Axure、Figma、Sketch它们各有优势但普遍存在两个问题原型和最终开发代码之间有一道翻译成本。产品经理在 Axure 里画的交互工程师要用 SwiftUI 重新实现一遍过程中容易出现视觉偏差和信息损耗。原型制作本身需要学习设计工具。很多开发者并不是专业设计师让他们用 Figma 搭一个复杂界面效率反而不高。用 Xcode 智能体创建 UI 原型时走的是一条更直接的路径自然语言需求 - SwiftUI 代码 - Xcode 实时预览因为输出的是真实代码所以这个原型不仅能用来看效果还能直接作为开发的基础版本继续迭代。对 iOS 开发者来说这种方式的学习成本最低。1.3 适用场景与能力边界为了不对结果产生不切实际的预期我先说清楚智能体适合做什么、不适合做什么。适合的场景快速验证产品想法比如一个工具类 App 的首页长什么样。生成多套视觉备选方案方便团队评审。生成 SwiftUI 组件库作为设计走查的基础素材。把一段技术调研 Demo 快速拼装成可展示的界面。不适合的场景高度依赖品牌视觉规范的大型产品页面智能体无法完全理解你的 Design Token 体系。复杂手势交互、自定义导航转场、大量动画细节。需要严格遵守无障碍规范的专业级应用界面。所以我通常会这样定义它的角色智能体负责把“能看”的东西先做出来人负责把“能看”变成“能用、好看、符合规范”。2. 环境准备与版本说明2.1 硬件与系统要求Xcode 智能体依赖系统级 AI 能力和最新 Xcode 工具链因此环境要求比普通 Xcode 开发更高一些。以我使用的环境为例项目建议配置电脑Apple Silicon MacM1 及以上芯片系统macOS 15 或更新版本XcodeXcode 26 或更新版本以 App Store 最新版为准网络需要能够正常访问 Apple 智能服务Apple 账户需要登录启用 Apple Intelligence 相关能力需要特别说明的是不同版本的 Xcode 对智能体功能的入口名称和功能完整性会略有差异。如果你的 Xcode 里找不到下文提到的菜单优先检查 Xcode 版本再去 Developer Settings 里确认智能体功能是否开启。2.2 创建测试工程为了让智能体有明确的“工作上下文”我建议不要直接在空文件里让智能体生成代码而是先创建一个最小的 iOS App 工程再让智能体在工程里发挥。打开 Xcode 后执行File - New - Project - iOS - App产品名称可以命名为TaskerPrototypeInterface 选择 SwiftUILanguage 选择 Swift。语言和界面框架的选择很重要因为智能体在生成 UI 原型时默认会以 SwiftUI 为主。如果你更习惯命令行也可以用xed快速打开或创建工程目录mkdir TaskerPrototype cd TaskerPrototype xed .用 Xcode 创建好工程后ContentView.swift是智能体最常操作的文件。为了后续方便管理建议保持默认文件结构不要急着改成复杂目录。2.3 给智能体授权工作目录Xcode 智能体的安全模型要求你明确指定它可以访问的目录。这个设计很重要下面章节会展开讲。打开智能体管理器后创建新的管理器时选择刚才创建的工程目录作为允许访问的范围。这样智能体就能读取工程内文件、创建新文件、执行有限的构建命令但不会拿到你整个磁盘的权限。3. Xcode 智能体核心能力拆解在进入实战之前有必要先理解 Xcode 智能体的几个核心机制。理解了这些你在写提示词和排查问题时都会更有方向。3.1 管理器与会话Xcode 智能体通过“管理器”来组织任务。一个管理器相当于一个独立的工作空间你可以为不同项目创建不同管理器避免多任务上下文互相污染。在管理器内部你可以开启多个会话Session每个会话围绕一个目标展开会话 A生成首页原型。会话 B为主界面添加深色模式适配。会话 C重构列表项的卡片样式。这种会话隔离机制在工程上非常重要因为智能体会把会话中的历史对话作为上下文如果你把无关需求混在同一个会话里容易导致它理解偏差。3.2 工具调用与工程操作智能体在运行时会调用一组工具来完成任务。常见工具能力包括工具能力作用读取文件分析当前代码结构写入文件修改 SwiftUI 代码、配置文件创建文件新增组件文件执行命令运行构建、格式检查等读取工程信息获取工程结构和依赖情况需要注意的是智能体只能在你授权的目录内执行这些操作这是苹果设计的安全边界。它不能不经允许就修改系统文件或访问个人文档这一点对工程安全非常友好。3.3 基于上下文的迭代智能体与传统“文本生成模型”最大的区别在于它有真实工程上下文。假设你让它“把按钮主题色改成蓝色”普通 AI 聊天工具只能给你一段蓝色按钮代码而智能体会先读取你的工程文件找到当前主题色定义在哪里然后直接修改对应位置并保证其他引用了该变量的界面同步生效。这也是为什么用智能体做 UI 原型时迭代的自然语言反馈能产生非常高效的工作流第一轮生成一个今日任务列表页。 第二轮列表项左侧加上完成勾选按钮。 第三轮把顶部标题改成大标题样式加一个深色模式适配。每一轮它都在上一轮的代码基础上修改而不是重新生成一份文件。这是它作为“智能体”而非“聊天机器人”的关键区别。3.4 代码审查与检查智能体完成代码修改后你不需要盲信结果。它在训练过程中已经掌握了大量 SwiftUI 编码规范但仍建议在预览前做两件事查看智能体生成的代码 diff确认没有大范围误改。使用 Xcode 的编译和预览功能验证界面是否正常。把智能体当作“一个水平中等偏上的协作者”是更合理的心态它负责产出初稿你负责验收和把关。4. 完整实战用智能体生成“今日任务”App 的 UI 原型下面通过一个完整案例走一遍从自然语言需求到可交互 UI 原型的全流程。这个案例会生成一个“今日任务”App包含任务列表、添加任务、完成状态切换等核心功能覆盖了 UI 原型最常见的场景。4.1 明确需求描述动手写提示词之前先把需求想清楚。这里我给出一份比较清晰的原始需求这是一个 iOS 今日任务管理 App 的原型。 功能要求 1. 主界面显示今日任务列表每个任务包含标题、截止时间和优先级标签。 2. 支持添加新任务添加按钮放在工具栏右上角。 3. 点击任务左侧的圆形按钮可以切换完成状态完成的任务用灰色显示并带有删除线。 4. 顶部支持按“全部 / 进行中 / 已完成”三个 Tab 筛选。 5. 数据先用内存数组模拟不需要接入真实数据库。 6. 使用 SwiftUI 实现界面风格现代简洁系统字体SF Symbols 图标。把需求写清楚是智能体生成高质量原型的基础。下文会专门讲提示词的结构这里先按上面的描述执行。4.2 创建智能体管理器并输入提示词在 Xcode 中打开智能体管理器创建一个新的管理器名称可以叫TaskerUI。设置授权目录为刚才创建的TaskerPrototype工程目录。新建会话后直接把 4.1 的需求粘贴进去并追加一句请先查看 ContentView.swift 的当前内容然后直接替换为完整实现。这一步的目的是让智能体明确“改哪个文件、改到什么程度”。如果不指定文件它可能会自己新建文件或者把代码写在错误位置。4.3 查看智能体生成的 SwiftUI 代码提交需求后智能体会生成一段代码。正常情况下它会修改ContentView.swift。为了演示下面是我整理出来的核心代码结构与智能体生成结果基本一致。// 文件路径TaskerPrototype/ContentView.swift import SwiftUI struct TaskItem: Identifiable { let id UUID() var title: String var dueTime: String var priority: Priority var isDone: Bool false } enum Priority: String, CaseIterable { case high 高 case medium 中 case low 低 } struct ContentView: View { State private var tasks: [TaskItem] [ TaskItem(title: 提交周报, dueTime: 09:30, priority: .high), TaskItem(title: 评审新版原型, dueTime: 11:00, priority: .medium), TaskItem(title: 预约会议室, dueTime: 14:00, priority: .low), TaskItem(title: 回复客户邮件, dueTime: 16:30, priority: .medium) ] State private var filter: Filter .all enum Filter: String, CaseIterable { case all 全部 case active 进行中 case done 已完成 } var filteredTasks: [TaskItem] { switch filter { case .all: return tasks case .active: return tasks.filter { !$0.isDone } case .done: return tasks.filter { $0.isDone } } } var body: some View { NavigationStack { VStack { Picker(筛选, selection: $filter) { ForEach(Filter.allCases, id: \.self) { item in Text(item.rawValue).tag(item) } } .pickerStyle(.segmented) .padding(.horizontal) List { ForEach(filteredTasks) { task in HStack { Button { toggleTask(task) } label: { Image(systemName: task.isDone ? checkmark.circle.fill : circle) .foregroundStyle(task.isDone ? .green : .secondary) .font(.title2) } .buttonStyle(.plain) VStack(alignment: .leading, spacing: 4) { Text(task.title) .strikethrough(task.isDone) .foregroundStyle(task.isDone ? .secondary : .primary) Text(task.dueTime) .font(.caption) .foregroundStyle(.secondary) } Spacer() Text(task.priority.rawValue) .font(.caption.bold()) .padding(.horizontal, 8) .padding(.vertical, 4) .background(priorityColor(task.priority)) .clipShape(Capsule()) } } } .listStyle(.plain) } .navigationTitle(今日任务) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { addTask() } label: { Image(systemName: plus) } } } } } private func toggleTask(_ task: TaskItem) { if let index tasks.firstIndex(where: { $0.id task.id }) { tasks[index].isDone.toggle() } } private func addTask() { tasks.append(TaskItem(title: 新任务, dueTime: 09:00, priority: .low)) } private func priorityColor(_ priority: Priority) - Color { switch priority { case .high: return .red.opacity(0.15) case .medium: return .orange.opacity(0.15) case .low: return .blue.opacity(0.15) } } } #Preview { ContentView() }这段代码并不复杂但它完成了原型阶段需要覆盖的四个关键点用State管理内存数据模拟真实数据源。使用NavigationStackToolbarItem搭建导航结构。用Picker实现分段筛选。用ListForEach渲染任务列表并支持完成状态切换。它最大的价值是数据结构清晰后续接入SwiftData或Core Data时只需要替换数据层UI 层可以基本保留。4.4 运行与验证原型拿到代码后先不要急着继续提需求。回到 Xcode选择模拟器点击运行按钮或者使用快捷键Command R。如果你更习惯命令行也可以在工程目录下执行xcodebuild -scheme TaskerPrototype -destination platformiOS Simulator,nameiPhone 16 build这里的nameiPhone 16需要根据你本机可用的模拟器调整可以先通过xcrun simctl list devices查看可用的设备列表。预期结果应该是顶部显示“今日任务”大标题。分段控件可以切换不同的任务状态。点击任务左侧圆圈任务会变灰并出现删除线。点击右上角加号列表会新增一条默认任务。如果这些都能正常操作说明原型的第一版已经跑通了。4.5 迭代修改更换主题色和空状态第一版原型跑通后开始第二轮迭代。在同一个会话里继续补充提示词原型基本可用。现在做两处优化 1. 把主色调从默认的蓝色改成靛青色indigo优先级标签的底色也统一调整到与主色调协调。 2. 当当前筛选结果为空时显示一个空状态视图包含一个 SF Symbol 图标和一句提示文案。智能体会读取当前代码并在已有基础上修改。它可能会引入一个新的emptyStateView类似这样if filteredTasks.isEmpty { ContentUnavailableView( 暂无任务, systemImage: checkmark.circle, description: Text(当前筛选条件下没有任何任务) ) }这里用到的ContentUnavailableView是 SwiftUI 系统组件非常适合空状态展示。你可以看到迭代修改的效率比第一轮生成还要高因为智能体不需要重新理解整个需求只需要做局部调整。5. 把原型落地为真实工程的检查清单智能体生成的 UI 原型虽然在结构上能跑通但离真正的生产级代码还有一段距离。以下是我在实际项目中总结的落地检查清单。5.1 数据层重构原型阶段通常使用State数组模拟数据它的问题在于App 重启后数据会丢失。多页面之间无法共享状态。无法处理复杂的增删改查逻辑。落地时建议替换为SwiftData或Core Data至少也应该用ObservableObjectPublished构建一个独立的 Store 层。// 示例使用 ObservableObject 管理任务状态 MainActor final class TaskStore: ObservableObject { Published var tasks: [TaskItem] [] func addTask(_ task: TaskItem) { tasks.append(task) } func toggleDone(for task: TaskItem) { if let index tasks.firstIndex(where: { $0.id task.id }) { tasks[index].isDone.toggle() } } }这个简单的 Store 层把数据管理和视图解耦后续替换成 SwiftData 时只需要修改TaskStore内部实现。5.2 视觉规范统一智能体在生成原型时颜色、字体、间距往往是“凭感觉”的。落地时建议抽出设计令牌Design Token// 文件路径TaskerPrototype/Theme/AppTheme.swift import SwiftUI extension Color { static let brandPrimary Color.indigo static let brandBackground Color(.systemGroupedBackground) static let priorityHigh Color.red.opacity(0.15) static let priorityMedium Color.orange.opacity(0.15) static let priorityLow Color.blue.opacity(0.15) }这样可以让不同页面的视觉保持统一也方便后续配合设计师调整。5.3 测试与可维护性原型阶段一般不写测试但落地阶段必须补上。特别是列表增删改查这类核心逻辑建议给TaskStore写单元测试。import XCTest testable import TaskerPrototype final class TaskStoreTests: XCTestCase { func testAddTask() { let store TaskStore() store.addTask(TaskItem(title: 测试, dueTime: 10:00, priority: .low)) XCTAssertEqual(store.tasks.count, 1) } func testToggleDone() { let store TaskStore() let task TaskItem(title: 测试, dueTime: 10:00, priority: .low) store.addTask(task) store.toggleDone(for: task) XCTAssertTrue(store.tasks.first?.isDone true) } }5.4 提交前必须人工 Review无论智能体多智能它生成代码的最终责任人仍然是开发人员。建议在提交代码前用 Xcode 的源码管理器查看 diff。检查是否引入无关改动。确认没有硬编码的测试数据残留在生产路径中。确认没有明显隐私风险比如把 API Key 写在视图里。6. 常见问题与排查思路在真实使用 Xcode 智能体的过程中可能会遇到一些常见问题。下面整理了一份排查清单方便你按图索骥。问题现象常见原因解决思路智能体管理器找不到工程文件授权目录没有包含工程所在文件夹重新创建管理器把授权范围扩展到工程根目录提示“无法访问文件”工程在 iCloud 或外部磁盘权限隔离导致把工程复制到本地磁盘后重试智能体生成后编译报错Xcode 版本与生成代码 API 不匹配检查 SwiftUI API 是否废弃手动修正后重新编译运行预览一直是白屏类型推断失败或存在运行时错误查看 Console 日志先修复编译错误再继续迭代智能体修改了多个无关文件提示词没有明确指定改动范围在提示词末尾追加“只修改 ContentView.swift”生成代码风格和工程不一致缺少项目规范上下文在提示词开头补充工程使用的命名规范、架构模式删除任务或新增任务没有刷新 UI数据模型没有遵循 Identifiable 或没有使用 State检查 ForEach 的数据源确保使用可观察状态排查问题时建议按照“先编译、后逻辑、再视觉”的顺序推进。智能体的报错通常比较直白把 Xcode 顶部错误提示截下来直接重新描述给智能体往往能快速得到修复方案。7. 最佳实践与工程建议7.1 提示词的结构化模板用智能体做 UI 原型提示词质量直接决定结果质量。我实践下来一个高成功率的提示词包含五个部分角色和背景你是资深 iOS SwiftUI 开发者正在为 [项目名] 创建原型。 当前任务需要实现 [具体页面/功能]。 功能拆解需要包含 [列表、弹窗、导航等]。 技术约束使用 SwiftUI数据用内存模拟文件只修改 [路径]。 验收标准运行后能达到 [预期效果] 即可。按这个模板写提示词智能体通常不会跑偏。7.2 小步迭代不要一次堆需求一次对话里塞五六个复杂需求智能体容易顾此失彼。更稳妥的做法是第一轮生成完整页面骨架。第二轮修正布局和间距。第三轮增加交互反馈。第四轮优化视觉细节。每一轮验证后再进入下一轮问题定位会容易很多。7.3 用 Git 管理智能体修改智能体自动改代码的能力虽然强但也意味着你可能对它具体改了什么没有完全掌控。建议在开始使用智能体之前先提交一次干净的基线版本git add . git commit -m chore: 智能体改造前基线之后每一轮智能体修改都通过 git diff 检查再提交。一旦发现改乱了可以直接回滚。7.4 隐私与合规边界虽然 Xcode 智能体在数据处理上有隐私设计但我仍不建议直接把包含敏感信息的代码原样发给智能体。比如真实数据库连接字符串。API Key 或签名密钥。未脱敏的用户数据。一般做法是在工程里准备一个对外演示的分支只包含模拟数据和干净的代码结构。这样既能利用智能体提升效率又不会把敏感信息暴露给外部模型服务。7.5 把智能体看成协作工具而不是依赖UI 原型是整个产品设计链路的第一环智能体能帮我们快速验证想法、降低沟通成本但它无法替代设计师对品牌细节的把握也无法替代工程师对稳定性、安全和性能的权衡。使用智能体时最好的心态是让它成为你的协作工具而不是你对产品理解的替代品。代码质量、交互细节、设计规范这些关键判断仍然需要人来完成。如果你正准备尝试新的原型工作流可以从今天这个“今日任务”案例开始把提示词改一改替换成你自己的产品场景跑通一遍然后再逐步扩展到更复杂的页面。当你发现一个想法从描述到可点击原型只需要几分钟时你会重新理解 AI 辅助开发这件事的潜力。