首页 / 资讯中心 / 文章详情

两个月九万行代码:我用coding agent开发macOS/iOS App的vibe coding实战

两个月九万行代码:我用coding agent开发macOS/iOS App的vibe coding实战 ★ FEATURED ARTICLE
1. 两个月写出一个 App我到底经历了什么先说结论这个 App 从第一行代码到上架 App Store总共九万多行我完整读过的代码大概不超过三百行。这不是炫耀也不是偷懒而是我在这两个月里刻意选择的一种开发方式——把绝大部分编码工作交给 coding agent自己只负责定义问题、验收结果、调整方向。整个过程下来我对“写代码”这件事的理解被彻底刷新了一遍。这个项目是一个 macOS 和 iOS 双端的效率类 App核心功能不复杂本地数据管理、快捷输入、跨设备同步、通知横幅提醒。听起来像是那种“一个人两周就能搞定”的东西但真正做起来光是 UI 适配、状态管理、数据持久化、通知权限、上架审核这几块就足够把一个独立开发者拖进泥潭。我之所以敢在两个月内推进是因为我把整个开发流程拆成了“我定义 → agent 实现 → 我验收 → agent 修复”的循环而不是传统的“我写 → 我调 → 我改”。vibe coding 这个词最近被讨论得很多但很多人理解得比较窄以为就是“对着 AI 说一句话代码就出来了”。实际体验下来它更像是一种新的协作节奏你不再逐行控制代码而是控制意图、边界和验收标准。coding agent 负责把意图翻译成可运行的代码你负责判断“这是不是我想要的”。这个转变听起来简单做起来非常反直觉因为你会不断遇到“代码能跑但不对”“功能对了但结构烂”“结构好了但性能崩”的情况。这篇文章我会把这九万行代码背后的完整流程拆开讲我怎么选工具、怎么定义任务、怎么验收、怎么处理 agent 写出来的烂代码、怎么在 macOS 和 iOS 之间做适配、怎么处理通知横幅这种细节、怎么上架、以及我踩过的那些坑。适合两类人看一类是想尝试 vibe coding 但不知道从哪下手的开发者另一类是对 coding agent 持怀疑态度、想看看真实项目里它到底能干什么的人。2. 为什么我选择“不读代码”这条路2.1 传统开发流程的瓶颈在哪里我做过不少独立项目传统流程大概是这样的先想清楚需求然后搭架构然后一个模块一个模块写写完自己测测完改改完再测。这个流程的问题不在于慢而在于上下文切换成本极高。你写 UI 的时候想着数据层写数据层的时候想着网络层写网络层的时候又担心 UI 状态同步。一个人做全栈最大的敌人不是技术难度而是脑子里同时挂着太多线程。更现实的问题是独立开发者最容易卡在“细节沼泽”里。比如 macOS 上做一个通知横幅你要处理权限申请、通知样式、点击回调、前台展示策略、免打扰时段、通知分组这些东西单独看都不难但加起来就是几百行代码和一堆边界情况。你花两天把这些做完回头一看核心功能还没动。这种消耗感是很多独立项目半途而废的直接原因。2.2 coding agent 真正改变的是什么coding agent 改变的不是“写代码的速度”而是你关注的对象。以前你关注的是“这行代码怎么写”现在你关注的是“这个行为对不对”。这个转变的关键在于agent 可以快速产出大量可运行代码但它的产出质量高度依赖你给它的约束。你给它的约束越清晰它产出的代码越接近可用你给它的约束越模糊它就越容易写出“看起来对但实际不能用”的东西。我在这两个月里最大的体会是agent 不是替代你思考而是替代你打字。它不会帮你决定“这个功能要不要做”“这个交互合不合理”“这个数据结构能不能扩展”这些仍然是你的工作。但它可以帮你把“我已经想清楚的东西”快速变成代码而且速度远超你自己写。2.3 为什么我敢不读代码不读代码的前提是验收标准足够硬。我给自己定了三条规则第一每个功能必须有可执行的验收用例不能靠“看起来对”来判断。第二关键路径必须有日志和断言出问题能定位到具体环节。第三任何 agent 产出的代码如果我要改必须先让它自己解释这段代码在干什么。这三条规则保证了我即使不逐行读代码也能对系统行为有足够掌控。换句话说我不是“不看代码”而是“不逐行读代码”我把阅读代码的精力换成了设计验收标准和排查路径。这个交换在两个月里被证明是划算的因为它让我把时间花在了真正需要人判断的地方。3. 工具选型我是怎么搭这套工作流的3.1 coding agent 的选择逻辑市面上 coding agent 工具不少我最终选的是一个支持多文件编辑、能跑终端命令、能读项目结构的 agent。选它的理由很实际它能在项目级别理解上下文而不是只处理单个文件。它能执行命令并读取输出这意味着它可以自己跑测试、自己看报错。它支持增量修改不会每次把整个文件重写一遍。这三点决定了它能不能参与“实现 → 验证 → 修复”的闭环。如果一个 agent 只能生成代码但不能验证代码那它就只是个高级自动补全价值有限。我实测下来能跑命令的 agent 和不能跑命令的 agent效率差距大概在三倍以上因为前者可以自己发现并修复大部分低级错误。3.2 macOS 和 iOS 双端项目的特殊处理这个项目要同时跑在 macOS 和 iOS 上这给 agent 带来了额外挑战。两个平台的 API 差异不小比如通知系统、文件访问、窗口管理都不一样。我的处理方式是把平台无关的逻辑抽成独立模块让 agent 只写一份。平台相关的部分单独建目录明确告诉 agent “这是 macOS 专用”“这是 iOS 专用”。每次让 agent 改代码时明确说明目标平台避免它把两个平台的代码混在一起。这个做法看起来笨但非常有效。因为 agent 最容易犯的错误就是“用 iOS 的 API 写 macOS 的代码”而一旦你把它隔离清楚这类错误基本就消失了。3.3 项目结构的设计原则我让 agent 参与开发之前先自己把项目结构定好了。这个结构不复杂但每一条都是为了让 agent 更容易理解project/ core/ # 平台无关逻辑 macos/ # macOS 专用 ios/ # iOS 专用 shared/ # 共享 UI 组件 tests/ # 验收用例 scripts/ # 构建和检查脚本这个结构的核心思想是按平台边界和职责边界切分而不是按技术层次切分。因为 agent 对“目录名”的敏感度远高于对“架构图”的理解你把边界写在目录名里它就不容易越界。提示不要指望 agent 理解你的架构意图它只能理解你写下来的约束。目录结构、命名规范、注释说明这些才是它真正的“架构文档”。4. 核心工作流从意图到可运行代码4.1 任务拆解多细才算细我一开始犯过一个错误给 agent 的任务太粗。比如我说“做一个通知横幅功能”它产出的代码能跑但样式不对、点击没反应、权限没处理。后来我把任务拆到这种粒度定义通知横幅的数据结构实现通知权限申请流程实现横幅 UI 布局实现点击回调实现前台展示策略写验收用例拆到这个粒度之后agent 的产出质量明显提升。原因是每个任务都有明确的输入和输出它不需要猜“你到底想要什么”。我总结的经验是任务粒度应该细到“你能用一句话描述验收标准”。如果你说不清楚怎么验收说明任务还不够细。4.2 提示词的结构化写法我用的提示词模板大概是这样目标实现 macOS 通知横幅的权限申请流程 约束 - 只在 macos/ 目录下修改 - 使用系统原生通知 API - 权限被拒绝时要有降级提示 - 不要修改 core/ 下的任何文件 验收 - 首次启动时弹出权限申请 - 拒绝后再次启动不重复弹窗 - 拒绝状态下功能可用但有提示这个模板的关键是约束和验收分开写。约束是“你不能做什么”验收是“我怎么判断你做对了”。这两块写清楚agent 的产出基本不会跑偏。我试过只写目标不写约束结果 agent 把通知逻辑写到了 core/ 目录里导致 iOS 端编译失败。从那以后我再也没省过约束这一块。4.3 验收用例的写法验收用例我坚持用可执行的方式写而不是用文字描述。比如通知权限这块我写的是func testNotificationPermissionDenied() { let manager NotificationManager() manager.mockPermissionStatus(.denied) manager.requestPermission() XCTAssertTrue(manager.shouldShowFallbackHint) XCTAssertFalse(manager.shouldRetryPermission) }这样写的好处是 agent 可以直接跑这个用例自己判断有没有通过。我实测下来有可执行验收用例的任务agent 一次通过率大概在七成左右没有验收用例的任务一次通过率不到三成。这个差距非常明显。4.4 迭代节奏一天几个循环我一天的节奏大概是这样的上午定义 3 到 5 个任务写清楚约束和验收。中午让 agent 跑第一轮收集失败用例。下午针对失败用例让 agent 修复通常两到三轮能收敛。晚上我自己跑一遍完整流程确认没有回归。这个节奏下我一天能推进的功能量大概相当于传统开发的三到四倍。但要注意这个倍率只在“任务拆得够细”的前提下成立。任务一粗倍率立刻掉下来因为你要花大量时间在返工上。5. 那些 agent 写出来的烂代码我是怎么处理的5.1 能跑但不对最常见的问题agent 最典型的产出是“能跑但不对”。比如通知横幅的样式它写出来的代码能显示但圆角不对、阴影太重、字体偏大。这类问题不是逻辑错误而是审美和规范问题。我的处理方式是把 UI 规范写成明确的数值比如“圆角 12pt、阴影透明度 0.15、字体 15pt”。让 agent 按数值实现而不是按“好看”实现。验收时用截图对比而不是靠肉眼判断。这个做法把主观问题变成了客观问题agent 处理起来就稳定多了。5.2 结构烂但功能对要不要重构agent 写出来的代码经常结构很烂比如一个函数干五件事、变量命名随意、重复代码多。我一开始想重构后来发现重构的成本比重新写还高。我的策略是如果这段代码只在一个地方用结构烂就烂不影响功能就不管。如果这段代码要在多个地方用就让 agent 重新写一个干净的版本而不是改旧的。如果这段代码是核心路径必须重构那就拆成小任务让 agent 一步步改。这个策略的核心是按影响范围决定是否重构而不是按代码质量决定。因为独立项目里代码质量的价值远低于功能交付的价值。5.3 性能问题什么时候该管agent 写出来的代码在性能上经常有问题比如列表滚动卡顿、内存占用高、启动慢。我的判断标准是如果用户能感知到必须管。如果用户感知不到先记下来等有空再管。如果是核心路径的性能问题立刻管。我遇到过最典型的性能问题是列表滚动卡顿原因是 agent 在每次滚动时都重新计算布局。这个问题用户能明显感知所以我让 agent 加了缓存问题就解决了。整个过程大概花了半小时比我手写缓存逻辑快得多。5.4 安全问题不能交给 agent 的部分有些东西我坚决不让 agent 碰比如密钥管理、数据加密、权限校验。这些部分我自己写或者至少自己逐行审。原因是 agent 对安全边界的理解很弱它容易写出“功能对但安全有漏洞”的代码。比如它可能会把密钥硬编码在代码里或者把权限校验写在客户端。这类问题一旦出后果比功能 bug 严重得多。注意agent 可以帮你写业务逻辑但不要让它碰安全相关的代码。这不是能力问题是责任问题。6. macOS 和 iOS 双端适配的实操细节6.1 通知系统的差异处理macOS 和 iOS 的通知系统差异很大。macOS 的通知横幅支持更多自定义iOS 的通知权限更严格。我的处理方式是在 core/ 里定义通知的抽象接口。在 macos/ 和 ios/ 里分别实现。用条件编译隔离平台代码。这样 agent 在改 macOS 通知时不会影响到 iOS 的实现。我实测下来这种隔离方式让双端适配的工作量减少了大概一半。6.2 数据持久化的统一方案数据持久化我选了一个跨平台的方案让 agent 只写一份逻辑。但要注意macOS 和 iOS 的文件访问权限不一样所以我在 core/ 里定义了存储接口在平台目录里实现具体的文件路径和权限处理。这样 agent 写业务逻辑时不需要关心平台差异写平台代码时又不会污染核心逻辑。6.3 UI 规范的统一与差异UI 这块我没有强行统一因为 macOS 和 iOS 的交互习惯本来就不一样。我的做法是共享颜色、字体、间距这些基础规范。平台特有的交互各自实现。用 shared/ 目录放真正通用的组件。这个划分让 agent 在写 UI 时有明确的边界不会把 macOS 的交互写到 iOS 上。6.4 构建和测试的双端流程构建流程我写了脚本让 agent 可以自己跑。macOS 和 iOS 的构建命令不一样我在 scripts/ 里分别放了 build-macos.sh 和 build-ios.shagent 需要构建时自己选。测试也是类似双端各跑各的。这个流程搭好之后agent 的自我验证能力明显提升因为它可以自己发现编译错误和测试失败。7. 上架 App Store 的那些坑7.1 审核被拒的常见原因我这个 App 上架时被拒过一次原因是隐私政策说明不完整。agent 帮我写的隐私政策模板缺少数据收集说明审核方要求补充。后来我补了完整的说明第二次就过了。这个经历让我意识到上架相关的文档不能完全交给 agent因为它对平台规则的理解不够细。7.2 截图和描述的准备工作截图和描述我花了大概两天准备。截图要覆盖主要功能描述要突出核心价值。这部分 agent 帮不上太多忙因为它不知道你的 App 到底解决什么问题。我的做法是自己写描述让 agent 帮忙润色和检查语法。7.3 版本管理和更新流程版本管理我用的是语义化版本每次更新都写清楚改了什么。agent 可以帮忙生成 changelog但最终的版本号决策还是我自己做。更新流程我写成了脚本让 agent 可以自己跑构建和打包减少手动操作。7.4 上架后的维护节奏上架后我保持每周一次小更新主要是修 bug 和优化体验。这个节奏下agent 的价值主要体现在“快速修复”上。用户反馈一个问题我定义任务agent 实现我验收当天就能发版。这个速度在传统开发流程里很难做到。8. 常见问题与排查技巧实录8.1 agent 产出不符合预期怎么办最常见的情况是 agent 产出的代码能跑但不符合预期。我的排查顺序是先看验收用例有没有覆盖这个预期。如果没覆盖补用例重新让 agent 做。如果覆盖了但没通过看是约束没写清楚还是 agent 理解错了。如果是约束问题补约束如果是理解问题换一种说法重新描述。这个顺序能解决九成以上的问题。剩下的一成通常是任务粒度太粗需要重新拆。8.2 编译错误反复出现怎么处理编译错误反复出现通常是因为 agent 改了不该改的文件。我的处理方式是检查最近的修改范围看有没有越界。如果有越界回滚重新定义约束。如果没有越界看是不是依赖冲突让 agent 自己跑依赖检查。我遇到过最麻烦的编译错误是依赖版本冲突agent 改了依赖版本但没同步更新锁文件。后来我让 agent 每次改依赖都必须跑一次完整构建这个问题就再没出现过。8.3 性能问题怎么定位性能问题我一般用两个手段定位日志和 profiler。日志让 agent 加profiler 我自己跑。定位到具体环节后再让 agent 优化。这个流程比让 agent 自己找性能问题高效得多因为它对性能瓶颈的判断经常不准。8.4 上架审核被拒怎么应对被拒之后先看拒因然后针对性修改。如果是文档问题自己改如果是功能问题定义任务让 agent 改。改完重新提交通常第二次就能过。我建议第一次提交前就把隐私政策、权限说明这些文档准备好能省不少时间。问题类型典型表现处理方式产出不符预期能跑但不对补验收用例重新定义任务编译错误反复报错检查修改范围回滚越界改动性能问题卡顿、内存高日志加 profiler 定位再让 agent 优化审核被拒隐私政策不完整自己补文档重新提交8.5 我踩过的三个大坑第一个坑是任务太粗。我一开始让 agent 做“整个通知模块”结果产出的代码结构混乱、平台代码混在一起。后来拆成六个小任务问题就解决了。第二个坑是没写约束。我让 agent 改一个功能没说明不能改哪些文件结果它把核心逻辑改了导致其他功能崩溃。后来我每次都给明确的文件范围。第三个坑是没跑验收。我有一次偷懒没跑验收用例直接提交结果上架后被用户发现一个明显 bug。从那以后我坚持每次提交前跑完整验收。提示这三个坑的共同点是“省了不该省的事”。vibe coding 省的是打字时间不是思考时间。约束、验收、范围这三样一个都不能省。9. 两个月下来的真实体会九万行代码我一行都没完整看过但我对每一行代码的行为都有判断。这不是因为我信任 agent而是因为我信任自己设计的验收标准和排查路径。vibe coding 的核心不是“让 AI 写代码”而是“把人的判断力集中在真正需要判断的地方”。这两个月里我最大的收获不是做出了一个 App而是找到了一种新的开发节奏定义问题、设定边界、验收结果、快速迭代。这个节奏让我一个人能推进以前需要小团队才能推进的项目。但它也有代价你必须非常清楚自己要什么否则 agent 会给你一堆看起来对但实际不能用的东西。如果你也想试这条路我的建议是从一个小功能开始把任务拆细、约束写清、验收做硬跑通一个完整循环之后再扩大规模。不要一上来就让它做整个项目那样你会在返工里耗尽耐心。等你跑通几个循环你会发现自己的关注点从“怎么写”变成了“要什么”这个转变本身就是最大的价值。
阅读完成 · 觉得有帮助?
咨询建站