起点 —— 上一篇挖的坑,这一篇填了
上一篇 写完 Claude Code 魔改 Halo 主题,文末我顺手挖了个坑——说下一步想试试用 Claude 做个 iOS App。当时吹牛成分 60%、好奇成分 40%,没想到这话放出去不到一周,App 真就写完提审了。
动手之前我给自己定了两个目标。
一是摸一下 Claude 的能力边界。Halo 主题那种活,网页端改改 CSS,对 Claude 来说是舒适区。iOS 开发就不一样——SwiftUI、SwiftData、真机调试、证书签名、App Store 审核,每一环都是新坑,我想看看咕咕坐副驾这事能跑多远。
二是真有这个需求。不是为了写博客硬编的场景——我自己就囤着一堆 VPS、域名、邮箱、SaaS 订阅,哪天哪个扣费、哪天哪个到期,全靠Notion记录肉眼盯。(好吧我承认起因其实是怕自己的搬瓦工、iON 等等传家宝 VPS 忘记续费 = =)。
上一篇的评论区,有朋友推荐了 Wallos——一个自托管的订阅管理工具。我确实很早之前 Docker 部署了一份(也出过教程),跑在自己 VPS 上。但 Wallos 的提醒路径是邮件——我经常忘记开邮箱…… 而且我的邮箱太多了……
手机这东西一天看 50 次。如果有一个 App 把提醒直接推到锁屏——肯定不会错过。
动机清晰了。
2026 年 4 月 21 日晚上 7 点 28 分,我在一个空文件夹里打开 Claude Code,告诉它:
「做一个 iOS App,追踪订阅和域名到期时间,本地存储,不要账号,不要云」——就这么开始。
图标 —— 一只带铃铛的鸽子
整个项目里,唯一一个从一开始我就想清楚、没让 Claude 瞎发挥的东西,就是这只鸽子。
- 🕊️ 鸽子 = 信使——按时把消息捎到
- 🔔 铃铛 = 通知——到点了响一声
- 🧡 粉橙渐变——压住"催债感"和"焦虑感",DueSub 做的是温柔的提醒,不是红底白字的「还有 3 天扣费!」
图标里的一图二喻,其实就是这个 App 的产品哲学——非打扰式、按时到达、不制造焦虑。
功能是"续费提醒",视觉符号是"捎着铃铛的信鸽"——我只用一句话把这个意向说给 Claude 听,基本上两版就过了。这也是这次协作里我觉得最神奇的地方——你脑子里模糊的画面,只要你能用一句话说清楚它的内核,Claude 基本能把它落到像素上。
当然也适配黑暗模式:
成品长这样
话不多说,直接上图。
主列表:支出和收入同屏对照,月付、季付、年付、一次性,所有周期一个列表里理清。顶部那个粉橙色的卡片显示「30 天内还有几笔」,是我自己每天打开 App 最想第一眼看到的信息。
主屏小组件:桌面上直接看 30 天内即将到期的 N 项,不用点进 App。对我来说这就是这个 App 存在的意义——你手机锁屏那一眼就能看到的东西,你不会忘记。
锁屏小组件:只显示下一笔——不用解锁、不用打开 App、锁屏状态下直接看到名字和剩余天数。这个我真的挺喜欢。
整个视觉语言贯穿的还是那个「非打扰式」的产品哲学——数字不标红、不用感叹号、不搞「紧急!」这种暴力美学,就是温柔地提醒你一句。
4 天 18 个 commit
我之前没写过 Swift,一行都没有。
Xcode也没装过。
SwiftUI、SwiftData、WidgetKit(分别是苹果用来做 iOS 界面、存本地数据、做桌面/锁屏小组件的三套框架)是啥,全是边做边查。但不妨碍我 4 天写完、上架、提审。
| 日期 | Commits | 主要内容 |
|---|---|---|
| 04-21(周二) | 7 | 初版 + 改名 + 图标 + 隐私声明 + 截图策略 |
| 04-22(周三) | 4 | 通知 P0 三连击 + 真机验证 + 修复上线 |
| 04-23(周四) | 3 | 多币种实时汇率(opt-in) |
| 04-24(周五) | 4 | Bundle ID 改名 + ASC 元数据 + 提交审核 |
我大部分时间在干嘛?打字、截图、点按钮。写需求、看效果、给 Claude 反馈「这里不对、那里要改、审美再收一点」。真正「坐键盘前敲 Swift 语法」的时间——几乎没有。
但这不是说 Claude Code 是魔法。它不是。它会在一个看起来简单的地方疯狂跑偏,能爽到停不下来,也能气到想砸键盘。
下面是翻车现场合集。
翻车现场 1:改名三连跳(放了自己一鸽子)
App 一开始没专门起名字,我自用编译好之后,手机里最早就显示叫「续费提醒」。土是土了点,但直白。
第二天我觉得这名字太像 90 年代共享软件,改叫 Renewly。英文名、现代感、听起来像个 SaaS。
然后我犯了一个很愚蠢的错误——没有第一时间去 App Store 查重名。名字定了、图标调了、本地化文件改了、隐私政策的 title 也换了——一直到我准备提交审核之前,才突然想起来去搜一下。被人占了。有一个已经在跑的订阅工具 app 也叫 Renewly,功能还不完全重叠——这种重名是 Apple 审核环节大概率会让你改的那种。
这个锅就是没经验导致的。作为一个日常就在 App Store 搜 app、自己也跑一堆自托管工具的人,「发布前先查名字」这种事不用别人教。我偏偏就忘了——咕咕本咕,放了自己一鸽子。
只能第三次改名。这次更彻底:英文叫 DueSub(Due + Subscription 的缝合),中文叫 续然(续是续费,然是自然、果然)。
踩完坑的经验——名字想好之后第一件事:去 App Store 和 Google Play 都搜一遍,再去 Namecheap 看看 .com 在不在(最好但不是必须),都空着再去设计图标、改代码、改本地化。我这次反过来做,付了 3 次改名的工时。
翻车现场 2:通知的三个坑(同一天翻了三次)
这个 App 最核心的功能是到期提醒——你订的 VPS 明天扣费,我提前 7 天、3 天、1 天推送,当天上午 9 点再补一刀。这个功能不对,整个 App 就是一个「带搜索框的表格」。
结果 04-22 那天我翻了三次车,一天修了三个 BUG。
坑一:九点以后打开 App,当天的提醒丢了。
调度逻辑是每天早上 9 点对「当天到期的项」推送一次。自测 OK。结果某天下午我打开 App,发现明明有一项今天到期,却没推送。根因是 App 长时间没启动,调度队列里根本没这条通知,系统自然不会补发。修法是 App 启动时 fallback 检查一次——当天有到期项、现在已经过 9 点、用户今天还没收到,就立刻补推。
坑二:自动续费的文案跟代码对不上。
设置页之前有个「自动续费项默认不提醒」的开关,文案写「你已经设置自动扣款了,不需要再提醒」。听起来很合理——但代码不是这么做的。代码里自动续费项依然推 7/3/1 天的提醒,只有当天 9 点不推。这种「你说的是 A,代码做的是 B」最阴——不 crash、不报错、但就是跟用户说好的不一样。改了文案——提前几天提一下不是坏事,是自动扣那一刻再来一下才烦。
坑三:App 开着的时候,通知横幅被系统吞了。
iOS 的默认行为——App 在前台时,系统不弹横幅。理由是 App 自己处理。这对聊天软件合理,对一个到期提醒 App 就是「你盯着屏幕的时候我就不提醒你」——有点傻缺。我真机上复现:早上 9 点 App 开着,该推的一声没响。我当时盯着屏幕看了 10 分钟,以为自己又写炸了。修法其实很简单——一行代码的事,让 App 主动告诉系统「前台也请弹」。
三个坑修完、真机回归测过,这一天我感受到了**「软件这事儿怎么每个角落都能翻车」**的经典真理。Claude 写代码很快,但它不会替你想清楚「用户下午 3 点才打开 App 会发生什么」——你得自己变成产品经理兼测试,一个个角落去踩。
翻车现场 3:Bundle ID 的最后一公里
全程最让我心里一凉的一次。
Apple 的 Bundle ID(可以理解成 App 的全球唯一身份证号)一旦在 App Store Connect 注册并提交过 build(也就是打包上传过一次安装文件),就不能改了——要改只能注册新 App ID、开新 App 记录,之前填的元数据、截图、审核资料全部作废从头来。
我最早的 Bundle ID 前缀用了我日常 handle,但开发者账号实名信息是另一个名字。两边对不上,Apple 校验过不去。
只能改 Bundle ID。改它意味着:
- Xcode 里所有 target 的 Bundle ID
- 主 App 和小组件共享数据用的 App Group
- 证书和描述文件要重签
- 测试机上装过的旧版全部失效,要重装
最阴的是 App Group(让主 App 和桌面小组件共享数据的一个"命名空间",Apple 规定这个名字全球唯一)。我旧的 group 名改新的时候报冲突,说这个名字有人用过(其实是我自己,几分钟前注册的、没删)。加了个 .shared 后缀绕过——这个本来不应该存在的后缀永远留在我代码里了,作为一个「我和 Apple 的命名空间规则打过架」的纪念。
修完、重签、重装、回归——折腾好一会儿才终于走到 App Store Connect 那一步。
翻车现场 4:App Store Connect 是一个 checkbox 地狱
到这一步我才意识到:写 App 只是上架这件事的冰山一角。真正的灾难在 ASC。
让我列一下这次填过的表(不完整,凭记忆):
- App 名称 / 副标题 / 推广文本 / 描述 / 关键词(英文中文两套)
- 主类别 / 副类别 / 年龄评级(一份 20 多题的问卷,问我「本 App 是否包含恐怖元素」——我做的是订阅提醒)
- 版本号 / 构建号 / 上架日期
- 隐私政策 URL(每种语言一份,英文一个、中文一个)
- Marketing URL / Support URL
- 12 张截图(6.9" iPhone,iPad 跳过只做 iPhone)
- App Icon 1024×1024
- App 隐私标签(和代码里的
PrivacyInfo.xcprivacy是两份独立的表,要自己保证内容一致) - 内容版权声明(不是 App 的版权,是 App 里用没用别人的素材)
- 出口合规性(加密算法使用)
- IDFA 使用声明
- DSA 欧盟合规声明(新增的,个人开发者选 Non-Trader 才不会公开家庭住址)
- App 审核联系方式 + 演示账户 + 审核备注
- 定价 + 可用国家地区
- Mac / Vision Pro 兼容性(默认勾,记得关)
- 发布方式(自动 / 手动)
整理这份清单用了一下午。一个勾一个勾过,途中踩的坑:
- 勾了「所有国家」才发现默认包括中国大陆——国区要备案我没备,赶紧去掉
- 英文的隐私政策 URL 填完以为就行——ASC 跳出红 banner:简体中文 - 隐私政策网址 - 此栏为必填项。每种语言要独立一个 URL
- 以为提交时会弹「出口合规 / IDFA / 内容版权」三连问——这次居然没弹。后来才知道如果你在 Info.plist / xcprivacy / App 信息页都提前答过了,ASC 不再来烦你
- 备注里写了 Settings 里有个 "Seed Sample Data" 按钮——结果代码里英文按钮实际叫 "Fill sample data"。自己的 App,按钮名都记错。这给 Apple reviewer 看到,他大概会觉得我连自己 app 都没摸熟
最后所有字段绿勾、红 banner 消失、「提交以供审核」按钮可点。深呼吸,点下去。
然后画面一片祥和。没有弹窗、没有「你确定吗」、没有任何仪式感——左侧栏那个黄色小点变成「正在等待审核」,就这样。
吐槽一下:上架 App 这个流程,真的太复杂了
我要认真吐一下槽。
Apple 的 App Store 是 iOS 生态的核心支柱,用户体验堪称行业标杆。但它对开发者的体验,是另一个世界。
作为一个独立开发者、副业开发者、个人开发者,你要面对:
- ¥688 / 年的开发者费($99)。App 一分钱不赚,每年也得续。这个我认——毕竟用了整套工具链和分发网络。但作为一个常年买小鸡的人,每年还是要叹一声——这笔钱够我买一台好的服务器了。
- 证书体系。App ID / Bundle ID / Provisioning Profile / Distribution Certificate / Push Certificate……随便一个过期,线上炸。
- ASC 的 30 多个字段 + 一堆合规声明。DSA、隐私标签、xcprivacy、内容版权、出口合规、IDFA、年龄问卷、类别、定价、可用区。
- 审核的黑盒。什么时候过、为什么过、拒了怎么改,全靠邮件 + Resolution Center。
- 多语言隔离填写。每个 locale 要独立填描述、关键词、URL——漏一个返工重来。
这套流程对成熟团队(有专门的 release manager 和 compliance)是日常,对一个摸着石头过河的独立开发者——「完成率劝退」比代码本身高 10 倍。我完全理解为什么那么多做了一半的 iOS App 最后没上架——不是代码没写完,是上架的活儿没人愿意干。
我这次能走完,95%的功劳给 Claude——不是它写代码快,是它陪我把这 30 多个 checkbox 一个一个过完。如果让我自己看 Apple 文档去填,我多半中途就放弃了。
顺便说一下国区(其实我想上的)
这次上架,我主动跳过了中国大陆区——但这不是我本意。
我本来是想上国区的。不是说看重国区下载量,就是觉得一个中文作者做的中文工具,中文应用商店里没它,多少有点别扭。
备案这事我是知道的。早几年折腾服务器域名的时候,我就顺手买了一个十年的 .cn 域名挂在腾讯云、老老实实走完了 ICP 备案;当时配套也买过一台大陆服务器——但国内服务器的体验真的让人一言难尽,带宽小得可怜还卖得贵,到期我就没续费了。反正我要跑的服务都在境外,非要在大陆放一台机器没必要。
这次准备上架国区,我盘算了一下以为挺简单——.cn 域名还在、备案号还在、腾讯云账号还在、实名信息跟 Apple 开发者账号对得上。填个备案号就完事了吧?
结果一查流程才发现:光域名备案不够,备案得绑定在一台「正在使用中」的境内服务器上。我那台大陆机子早停了,备案跟着就失效了——要恢复,得再租一台国内服务器。
这就有意思了——我这个 App 完全离线、不联网、不部署任何东西。我不需要服务器,没有任何后端服务要跑,也没有任何 API 要托管。仅仅因为「要在国区上架」这个理由,我被强制要求去租一台我完全用不上的大陆服务器。
这一点我是真的不太理解。规则的本意大概是想给在国区上架的 App 留一个可追溯的境内主体,但对一个纯离线工具来说,服务器这条要求完全是空转——我没有后端、没有数据回传、没有任何需要境内托管的东西,却要为此每年多掏一份云厂商的钱。
算一下数:国内一台够用的轻量应用服务器(能用于备案的最低配起),一年 400 块起步;加上 Apple 开发者 ¥688;加上偶尔维护备案的小成本——对一个不收费的免费 App,每年多花 1000 多块为爱发电,实在不太合理。
所以这次我选了 All Countries except China mainland——174 个区全部开放,国区先空着。等哪天要做付费功能,有盈利模型能把这 1000 多块年成本覆盖掉,再回头补上国区不迟。
如果你也是个人开发者、做的是免费离线工具——国区这件事可以先放一放。把其他 174 个区跑通、把用户反馈收起来、把付费模型验证出来,再回头说国内的事。
Claude Code 作为 iOS IDE 的体验
回到这次最初的目标之一——「摸一下能力边界」。
我不懂 Swift,不会 SwiftUI 的声明式语法,SwiftData 的 @Model 到现在也讲不清原理。但一点都不慌——因为我不需要懂,我只需要知道我要什么。
- 「加一个设置项,让用户切换显示货币」——Claude 去加
- 「这个列表行高再紧一点」——Claude 去改
- 「真机跑一下,别只编译通过」——Claude 真的会去 build、装真机、抓日志
- 「这个通知为啥没弹,你查一下」——Claude 读上下文、看 delegate、写假设、去验证
我的角色从「写代码」变成了「定需求 + 审效果 + 做判断」。前者要懂语法,后者要懂用户。
爽的地方:你不再因为「不会 Swift」而放弃 iOS App 这个想法。
不爽的地方:它跑偏的时候你得看得出来——代码能力不是凭空被替代的,你能让 Claude 写代码,但你必须能看出它写的是不是你要的。
这次 4 天我踩到的能力边界大致在:
- 需要你当产品经理。Claude 不会主动想「用户下午 3 点打开会怎样」这种边界 case
- 需要你当测试。它说「已修复」不等于修了,必须你跑一遍真机复现
- 证书 / 签名 / 打包的坑它不一定记得住,要你盯着它去查 Apple 最新文档
- ASC 的字段含义它有时候会猜错,你得自己去对官方说明
其他的——写代码、读 API、调 debug、查栈、写测试——它比我快得多得多。
成本账
粗略算一下这个 App 到目前为止的总投入:
| 项 | 成本 |
|---|---|
| Apple 开发者账号 | ¥688 / 年 |
| Claude Code 订阅 | 已订的 Max 档,这次没多花 |
| 域名 + 托管 | ¥0(Landing 和隐私政策挂 GitHub Pages) |
| 服务器 | ¥0(没备案,不需要) |
| 图标 | ¥0(Claude + SF Symbols + 手调) |
| 截图 | ¥0(模拟器截图 + 简单标题文字) |
| 总计 | ¥688 |
跳过国区之后,全部成本就剩一张 Apple 开发者年费。对一个本来一行 Swift 都没写过的人——这个投入产出比,放在 Claude Code 出现之前是完全不可想象的。
写在最后
这不是一篇「你也能 4 天做 iOS App」的鸡血文。你不能,我也不能——如果换一个更复杂的 App(联网、账号、支付、音视频、AI 推理),这个周期会翻好几倍。
但有一件事值得说——「我不会写代码」,不再是做东西的理由了。
过去十年,「有想法但不会写代码」是劝退无数人的天花板。想做的东西卡在「找不到技术合伙人 / 招不起开发」这一步上。今天这个天花板被 Claude Code 这类工具狠狠砸了一个洞。
不是洞下面一切都容易,iOS 上架流程该复杂还是复杂,国区备案的门槛该离谱还是离谱。但写代码本身这件事,从「不可能」,变成了「要不要动手」。
当开发成本降到接近于零,真正稀缺的是什么
这次最让我想明白的一件事——开发成本的下降,反过来把产品问题推到了台前。
过去「找到真实需求 + 招到靠谱开发 + 写出能用的代码」三件事捆在一起,能搞定其中任何一个都算稀罕。现在 Claude Code 把第二、第三件事的门槛降到了个人能承受的范围——那第一件事——你到底在解决一个真问题,还是在自嗨——就变成了唯一卡住你的那个门槛。
我这个 App 是我自己的小真实痛点。规模不大,也不打算做成生意。但在做的过程里我越来越相信——在今天,独立开发者是真的能吃上饭的。这两年海外 indie dev 圈里,赚到钱的人一抓一大把,有年收入几十万美金的,也有做个 $10/月小工具把生活费搞出来的。核心都不是他们代码写得多牛——而是他们找到了一小群真实付费用户的真实需求。
代码这条护城河正在被填掉,用户洞察成了新的护城河。对不少想副业糊口、或者想看能不能全职独立的人,这可能是十年难遇的一个窗口期——代码能力第一次不再是硬卡点,但同时,你对用户的理解的重要性被放大到前所未有。
下一个坑
这次 DueSub 是免费 App,没盈利模型——它本来就是给我自己用的,顺手做成了产品。下一个我想挖的坑,是做一个带付费功能的 App:走一遍订阅 / 一次性内购的完整流程,去碰 StoreKit、走税务合规、看看 Apple 30% 抽水到底怎么切、体验一下从 0 到第一个付费用户的全过程。
具体做啥还没定——先把用户洞察这一步想清楚再动手。这次改名三连已经告诉我了,想清楚再动手,比手快多跑一版省事得多。
最后
回到博客侧边栏那四个字——learn or earn。
这回 learn 到了 iOS 一整套流程、Claude 能力边界、App Store 审核的全部坑;earn 谈不上,免费 App 没盈利模型。但摸清一条从 0 到 1 的路径本身,就是这次最大的 earn——下一次就知道怎么走第二步了。
App 叫 DueSub / 续然,现在在审核队列里,预计 24–48 小时后上架非国区 App Store。免费、离线、不要账号——如果你也跟我一样囤着一堆 VPS 和域名、又老忘开邮箱——装一个试试。
国区的事儿,以后再说吧。
咕咕下一篇接着挖坑。
后记 · 发博客之前 App 先过审了
正文写到上面那段「在审核队列里,预计 24-48 小时」的时候,App 确实还在审核。结果博客还没来得及排版发出,苹果那边先完事了。
这篇博客发出来的时候,App 就已经在除中国大陆外的各区 App Store 可搜可下了:
DueSub: Subscription Tracker —— 免费、离线、无需登录。
评论区