上个月查信用卡账单,发现一个扣了我 18 块的订阅——某个 AI 写作工具,试用期过了自动续费,我完全忘了它的存在。这事儿让我有点难受,不是因为钱,是因为这种「被偷走」的感觉。
查了一圈发现,我当时在跑的订阅服务加起来每月快 300 块,其中至少三个我已经半年没打开过了。
于是我做了「订阅斩」(SubKiller),一个帮你追踪、审查、干掉不需要订阅的 iOS App。
产品核心逻辑:不只是记账
市面上的订阅管理工具大多是「记录型」的——你告诉它你有什么,它帮你列出来。但我觉得这不够,因为问题根本不是「不知道自己有哪些订阅」,而是懒得去审查它们。
所以我在 SubKiller 里加了一个风险检测机制:App 会根据订阅状态(比如距上次使用时间、是否在试用期、账单周期是否临近)给每个订阅打风险等级,分高危和中危。高危订阅会主动推提醒,不用你自己去翻。
另一个设计是「斩」的交互。停用一个订阅不叫「删除」,叫「斩断」——有个动效,斩断后的订阅会进入「已斩」Tab,可以随时恢复。这个设计带来一点仪式感,把「停掉一个没用的订阅」变成一个有成就感的主动动作,而不是默默删个记录。
技术实现:SwiftData + BillingCycle 折算
数据层用的 SwiftData,Subscription model 存了名称、价格、账单周期、下次扣费日期、状态等字段。
账单周期是我花时间琢磨了一下的地方。用户可能按月付、按季付、按年付,但仪表盘要展示「每月预计支出」,所以需要折算。我用了一个 BillingCycle enum 来统一处理:
enum BillingCycle: Int, CaseIterable {
case monthly = 0
case quarterly = 1
case yearly = 2
var multiplierToMonthly: Double {
switch self {
case .monthly: 1
case .quarterly: 1.0 / 3.0
case .yearly: 1.0 / 12.0
}
}
}
有了这个 multiplier,任何订阅折算成月均成本只需要 price * multiplierToMonthly,仪表盘加总时直接用,逻辑干净。
货币这块也处理了一下国际化。AppSettings 里有个 defaultCurrencySymbol() 会读设备 Locale 推断默认货币符号,支持 CNY、USD、EUR、JPY、KRW 等十来个主要货币,不用用户手动选。
static func defaultCurrencySymbol() -> String {
switch Locale.current.currency?.identifier ?? "CNY" {
case "USD": return "$"
case "EUR": return "€"
case "JPY": return "JP¥"
case "KRW": return "₩"
case "TWD": return "NT$"
default: return "¥"
}
}
看起来很小的细节,但如果默认给一个台湾用户显示 ¥,体验就很割裂。
订阅预设库:省掉用户手动填
录入订阅是最容易劝退用户的一步。我内置了一个 SubscriptionCatalog,收录了 Netflix、YouTube Premium、Disney+、Apple TV+、iCloud、ChatGPT Plus 等几十个常见服务,包含图标、建议周期、参考价格。
用户输入服务名称时会做模糊匹配(有 alias 列表,比如「youtube」能匹配到「YouTube Premium」),自动填充大部分字段,用户只需要确认价格和下次扣费日期就行。这个设计把录入一条订阅的时间压到了大概 20 秒。
有个功能我试了三个方案,全删了
早期我想做「自动识别银行短信/邮件里的扣费记录」,想着这样用户根本不用手动录入。试了三个思路:
- 解析通知权限读短信 → iOS 根本不给这个权限,死路
- 让用户截图,用 OCR 识别 → 准确率不稳定,而且不同银行格式差太多
- 做一个「分享账单截图进 App」的 Share Extension → 开发量大,而且用户粘性不够,不值得
最后全删了,回到「内置预设 + 快速录入」的路子。说实话有点可惜,但做产品就是这样,有些想法在纸上很美,实现起来代价太高。
OCR 功能保留了一个简化版——可以扫描账单截图里的金额数字,但不做全自动录入,只是辅助填数字。这个改成按次限量使用,AppSettings 里有 ocrUsageCountStorage 和 ocrUsageResetDateStorage 两个字段做频次控制,Pro 用户不限次,免费用户每月有额度。
仪表盘设计:让数字「疼」一点
纯数字没什么感觉。「每月订阅支出 287 元」和「每月订阅支出相当于你 4.3 小时的工资」,后者会让你真的停下来想一想。
所以 AppSettings 里存了用户的月薪和月均工时,仪表盘会把订阅支出折算成「工作时长」。这个设计灵感来自一个很老的观点:评估一件东西值不值,用它需要你工作多少小时来衡量,比直接看价格更直觉。
这个字段是可选的,不想填的用户跳过就行,不影响基础功能。
App 现状
1.1 版本刚上线不久,下载量还很少,没什么可拿出来说的数据。我自己用下来,每周会打开一两次,主要是看风险提醒有没有新的高危订阅冒出来。
功能上还有几个地方我打算继续做:iCloud 同步目前已经支持,但多设备的冲突处理逻辑还有点粗糙;订阅分类统计(流媒体、生产力工具、游戏等)的图表展示还比较简单,想做得更直观一点。
如果你也有订阅管理的经验,或者对风险检测的判断逻辑有什么想法,欢迎在评论区聊。我比较好奇大家觉得「高危订阅」的判定标准应该怎么设——现在我用的是「超过 60 天未使用 + 账单临近」这个组合,但这个阈值其实是我拍的,不一定对。