App Store 说了"Yes"
两周前我写:"还在做,还没完成。"今天,DIALØGUE 已经在 App Store 上线了。最后那 40% 到底长什么样?
两周前,我在一篇博客末尾写:"还在做。还没完成。还没想好怎么跟女儿解释。"
我答应过,等 app 上了 App Store 就回来写后续。被拒了也写。我说过,被拒的故事说不定比通过更好看。
DIALØGUE - AI Podcast Studio 现已在 App Store 上线——一款原生 SwiftUI iOS 应用,能把任何话题或 PDF 变成一集完整的播客,由一个从没写过 Swift 的人用 Claude Code 搭建完成。 现在就能下载。
但不是一次就过的。说实话,我一开始就觉得被拒的故事会更精彩。果然被我说中了。
第一次提交被拒了,然后呢?
第一次提交被拒了。Guideline 2.1——性能:App 完整性。内购功能有问题。
Apple 的审核反馈倒是挺客气——他们注意到这是我第一次提交,还恭喜我加入了开发者计划,然后清楚说明了问题:审核人员尝试购买时,内购商品报错了。
关键在于:我自己测试的时候,购买流程完全没问题。问题出在 Apple 的沙盒环境——它的行为跟开发环境和生产环境都不一样。StoreKit 配置必须和 App Store Connect 完全一致,而我的没做到。我一直在用本地 StoreKit 配置文件测试,审核人员访问的却是真实沙盒。
当天修好,重新提交,过了。紧接着发了 v1.0.1 的 bug 修复,也顺利过审。
总共三次提交,一次被拒。那次被拒教给我的东西,比两次通过加起来还多。是不是很熟悉的规律?失败永远比成功更有教育意义。
"最后 40%"长什么样?
在那篇原帖里,我说 AI 能帮你搞定 60%,剩下 40% 全靠人。现在我可以说得更具体了,因为有 git 日志为证。
16 次提交。57 个文件变动。新增 4,886 行代码。 App 从 69 个 Swift 文件长到 88 个,从 7,568 行长到 11,459 行。差不多 4,000 行的"打磨"。
这 16 次提交里到底装了什么——大致按时间顺序:
本来第一天就该写的测试
原始脚手架有零个测试。零。Claude 写了 69 个生产代码文件,一行测试都没有。原帖发完后,我的第一个正式提交就加了 176 个单元测试和 19 个集成测试,跑在本地 Supabase 实例上。
写测试的过程马上就暴露出真实的 bug:Show 模型因为数据库字段不存在导致解码失败;AudioPlayer 播完一集没有重置;一个库重新加载的竞争条件;创建向导里少了对 nil UUID 的防护。每一个放到生产环境都是崩溃。
我觉得这个现象值得命名:AI 生成的代码没有测试基础设施。 不是它不会写——让 Claude 写测试,它写得挺好——而是初始脚手架的提示词永远是"帮我做这个 app",不是"帮我做这个 app 外加完整的测试"。测试是我自己决定加的,因为我不想在没有测试的情况下上线。
Studio:从空壳到真功能
原来的"Studio"就是个占位符。两次提交之后,它变成了真正能用的东西:模板网格的节目创建流程、带状态标签和操作按钮的单集管理、编辑/删除流程、带时区选择器的排期设置,还有声音自定义面板。
然后是 Studio 第二阶段:节目详情页重新设计、单集重试/删除、手动生成单集并检查积分余额。另加 8 个新的 XCUITest 确保端到端没问题。
这就是我说"AI 造了一个代码库,不是一个产品"的意思。Studio 编译能过,也能渲染出界面。但你根本没法拿它来管理一个定期更新的播客节目。
音频播放器重做
我在原帖里说删掉了迷你播放器。结果说错了——最后我做了一个更好的迷你播放器。最终版是一个固定在 Tab 栏上方的播放条,带进度、快进/快退和播放/暂停。点一下展开"正在播放"面板,里面有可拖拽进度条、倍速选择(0.5x 到 2x)、播放控制,还有一个声波动画封面。
最坑的是 isSeeking 状态——没有它,进度条位置和音频观察者互相打架,疯狂抖动。就这一行状态,我花了一个小时才定位到。
我还加了离线下载,配了一套完整的视觉反馈:库里已下载的单集显示绿色图标,下载完成弹提示,"正在播放"界面显示"已下载"标签,还能滑动删除下载。DownloadManager 里有一个临时文件竞争条件,藏在 URLSession 的 delegate 回调里,会无声失败——修复方法是在回调内部同步移动文件。这种 bug 在代码审查里是发现不了的。
全栈安全加固
这部分挺让人后怕的。对整个技术栈做了安全审计——不只是 iOS app——发现了好几层问题:权限开得太大的数据库函数、认证边界情况、Token 验证缺口,还有多个后端服务里的输入验证漏洞。
这些问题没有一个在 iOS Swift 代码里。全在 iOS app 调用的后端。但上架 iOS app 意味着你的整个技术栈装进了用户口袋。所有东西的风险等级一下子就上去了。以前一个 Web App "能跑就行"的代码,放到要过 Apple 审核、被人随身带着的原生 app 里,突然就觉得不能接受了。
StoreKit:直接把第一次提交干掉的坑
StoreKit 沙盒测试是一个独立的宇宙,也正是它让我第一次提交被拒了。 沙盒和生产环境行为不一样。交易有时候会一直卡在"pending"不动。Xcode 的 StoreKit 配置文件需要手动同步。我花了一整个晚上排查一个在代码里跑得好好的、在沙盒里却无声失败的购买流程——最后发现 App Store Connect 里的商品 ID 末尾多了一个空格。一个空格。
Apple 审核人员碰到了沙盒报错,因为我的 StoreKit 配置和 App Store Connect 没同步。购买流程在我本地测试完全正常——但审核人员访问的是真实沙盒,不是我的本地配置文件。当天修好了,但这个例子完美诠释了"我电脑上能跑"和"Apple 环境里能跑"之间的鸿沟。
购买验证链本身就是一个独立项目:iOS app 把交易以 JWS(JSON Web Signature)格式发给服务端函数,服务端对 Apple 签名的收据做完整的加密链验证。不是只解码——是真正的签名校验。这部分花了两次专项提交才搞定。
隐私与 App Store 合规
隐私和合规就是填表、做决定、打勾,每个勾都有法律含义——这些事 AI 帮不了你。 App 追踪透明度声明、隐私营养标签、加密出口合规(没错,HTTPS 也算)、内容版权、Turnstile 验证码集成。Claude Code 能写 Swift,但它没法告诉你你的数据收集行为要不要标注"用于追踪您的数据"。
完整的 MFA 和多语言
原来的 MFA 实现就是个半成品——空的 factor ID,只有验证流程。我把它重写成了完整的 TOTP 生命周期:注册、扫二维码(原生 CoreImage 生成)、验证、查看状态、停用。一个 394 行的 MFAView.swift,之前压根不存在。
7 种语言的本地化意味着 253 条 UI 字符串,翻译成英语、西班牙语、法语、日语、韩语、越南语和中文。翻译是 Claude 做的,大部分还行。但日语的"大部分还行"意味着你可能有一个按钮标签语法没错、读起来却像机器人写的。我把手机语言切过去实际用了一遍,才发现好几处这样的问题。这种测试,AI 目前还做不到。
DIALØGUE iOS App 能干嘛?
没看过原始构建故事的朋友,简单介绍一下 DIALØGUE:
你给它一个话题——或者传一个 PDF——它就能生成一集有研究、有剧本、有配音的播客节目。两位 AI 主播围绕你的话题自然对话,背后有真实的资料支撑。不需要麦克风。
iOS App 包含:
- 5 步创建向导 — 话题、格式、自定义、大纲审核、剧本审核
- 7 种语言共 30 种 AI 声音 — 英语、西班牙语、法语、日语、韩语、越南语、中文
- 9 种播客格式 — 从科技新闻分析到调查喜剧
- 带锁屏控制的音频播放 — 后台播放开箱即用
- Apple 登录、Google OAuth 和邮箱注册
- 应用内购买 — 积分制,无订阅:4 积分 $4.99,9 积分 $9.99,18 积分 $19.99
- Studio — 设置定期节目,自动生成最新单集
- PDF 上传 — 研究论文、报告、书籍都可以作为素材
这是真正的原生 SwiftUI app。不是 Web 套壳,不是 React Native。从最初 69 个 Swift 文件,到现在 88 个文件、11,459 行代码,195 个测试兜底。说实话,能把它发出来,我真的挺骄傲的。
我对"打磨阶段"的估计差了多远?
我之前写 app"还在开发中,处于最后打磨阶段"。技术上没错,但我严重低估了"打磨"里有多少其实是全新的活儿。
现在回头看 git 日志,16 次提交怎么看都不像"打磨"。更像是第二阶段开发。光测试套件——176 个单元测试和 19 个集成测试——就是一个完整的项目。Studio 从占位符变成了完整功能。音频播放器重做了两遍。安全加固涉及 40 多个后端函数。MFA 从头重写。
我还说删掉了迷你播放器。也说错了——最后我做了一个更好的,带"正在播放"面板、倍速控制和下载指示器。当初"删掉它"的直觉是对的——第一版迷你播放器确实很烂。但这个概念没错,只是需要好好做。
现在能看到全貌了,我觉得更诚实的比例是:AI 打地基(60%),人来做产品(30%),App Store 提交过程教你剩下的 10%。
欧盟能下载吗?
DIALØGUE 全球可用,但欧盟区域还在等 Apple 审核。 欧盟的《数字市场法》要求额外的合规步骤——替代支付方式披露、隐私文档、企业注册信息。材料我都交了,在等 Apple 那边处理。欧盟应该很快就能上。
等不及的话,Web 版在哪儿都能用,功能一样。
AI 辅助 iOS 开发到底能多快?
DIALØGUE iOS App 从第一次提交到 App Store 过审大约两周——一个晚上 AI 搭脚手架,加两周人工打磨产品。 我一直在更新这张表,因为它不断刷新我的认知:
| 项目 | 复杂度 | 构建时间 |
|---|---|---|
| DIALØGUE v1 | MVP 播客生成器 | 约 6 个月 |
| STRAŦUM | 10 个 AI 智能体、11 个框架、多租户 | 75 天 |
| 网站重新设计 | WordPress 前端大改 | 3 天 |
| DIALØGUE v2 | 完整 Web App 重建 | 14 天 |
| 博客迁移 | WordPress → Next.js,490 篇文章,Sydney RAG | 4 天 |
| DIALØGUE iOS | 原生 iOS App,第一次写 Swift | 约 2 周(脚手架:一个晚上) |
DIALØGUE iOS 从脚手架到上架大约两周。脚手架本身只用了一个晚上。这个比例——一个晚上的 AI 工作,两周的人工工作——基本说明了我们在 AI 辅助开发上走到了哪一步。
AI 的部分一直在变快。人的部分基本没变。两周前我这么写,现在依然如此。
AI 帮你写代码之后,什么能力反而更重要?
原帖里,我还没想清楚该给什么建议。"学会做那个打开模拟器的人"是当时能想到最好的答案。
现在东西真的上线了,我觉得可以说得更具体一点。
这个 App 能存在,靠的是三件 AI 做不到的事:
-
我在用这个产品。 不是测试——是真的在用。我自己创建播客,通勤路上听。我发现大纲审核界面需要显示研究来源,因为我想知道那些事实是哪来的。
-
我做了没有标准答案的判断。 迷你播放器删还是留?创建向导里多少自定义选项算太多?Studio 该做成一个 Tab 还是页面里的一个区块?这些不是工程决策,是品味决策。品味来自用过很多产品——好的烂的都算——然后慢慢养出一种对"感觉对了"的直觉。
-
我在一个给人设计的系统里找路。 App Store Connect、隐私声明、出口合规、截图规范——这些没法自动化。它需要你去读、去理解上下文、去判断法律和商业上的风险。这种能力——在复杂的人类系统里穿行——不会消失。
所以也许更新后的建议是:深度使用东西,通过在乎质量来培养品味,然后习惯在那些本来就不简单的系统里摸索方向。
这比"学会批判性思考"具体。我觉得更接近真相。但我还是不确定够不够。
怎么下载?
App 免费,内购积分制,没有订阅。
全球可用——欧盟区域还在 Apple 处理中,应该很快上线。Web 版随时随地都能用。
常见问题
DIALØGUE 上架了吗?
上了!DIALØGUE - AI Podcast Studio 已于 2026 年 3 月在 App Store 上线。免费下载,内购积分制(4 积分 $4.99,9 积分 $9.99,18 积分 $19.99)。全球可用——欧盟区域已提交,Apple 处理中。
欧盟能用吗?
已提交,Apple 处理中。欧盟的《数字市场法》要求额外合规步骤,材料我都交了,就等审核。应该很快。Web 版在哪儿都能用,包括欧盟。
Apple 拒过吗?
拒过——第一次提交因为内购有问题被拒了(Guideline 2.1:App 完整性)。StoreKit 沙盒配置和 App Store Connect 没同步,审核时购买报错。当天修好,重新提交,过了。之后 v1.0.1 也顺利过审。总共三次提交,一次被拒。那次被拒教给我的比两次通过加起来还多。
整个过程花了多久?
从原帖发布到 App Store 过审大约两周。Claude Code 一个晚上搭了 69 个 Swift 文件。后续 16 次提交新增 4,886 行代码,涉及 57 个文件——测试、Studio 功能、音频播放器重做、MFA 重写、安全加固、StoreKit 验证、多语言,还有 App Store 提交流程。最终上架:88 个文件,11,459 行代码,195 个测试。
最后 40% 里最难的是什么?
StoreKit 沙盒测试。"代码里能跑"和"Apple 的交易系统里能跑"之间的鸿沟非常大。沙盒交易行为跟生产环境不一样,商品 ID 必须完全匹配(空格都算),反馈循环还很慢——你没法直接跑个单元测试验证。
Web 版还能用吗?
当然。podcast.chandlernguyen.com 功能完全一样,什么设备都行。iOS App 多了一些原生体验——Apple 登录、锁屏控制、离线下载——但核心的播客生成体验是一样的。
还没想好怎么跟女儿解释。但至少现在有个上了架的 App 可以指着说:"人做的那部分,才是真正难的。"
祝好,Chandler








