news 2026/5/1 5:11:25

独立开发记录:我怎么把一个专注计时器做成了「声音护照」— iOS端技术拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
独立开发记录:我怎么把一个专注计时器做成了「声音护照」— iOS端技术拆解

为什么要做这个App

去年我给自己定了个规矩,每天至少专注写稿25分钟。试了一圈市面上的番茄钟,发现都是同一个套路:倒计时、叮一声、结束。

用了两周就不想打开了。没有留存感,没有成就感,就是个闹钟。

我想要的是——每次专注结束后,能看到点什么东西。像打游戏一样有经验条在涨,像跑步一样有公里数在累积。所以去年12月我上架了「声境护照」,把专注计时包装成了一段段飞行旅程。

现在版本 1.4,说实话下载量很一般,但这个项目本身让我学到了不少东西,值得记录一下。

数据模型:把专注包装成「远征」

我设计了一套叫 Expedition 的数据结构。每个"章节"对应一座城市(也就是一个声景),章节下面挂着几个任务:

structExpeditionChapterDefinition:Identifiable,Codable,Equatable{letid:StringletsceneId:StringletcityName:Stringlettagline:StringletbonusBounces:Intletmissions:[ExpeditionMissionDefinition]}structExpeditionMissionDefinition:Identifiable,Codable,Equatable{letid:Stringlettitle:Stringletkind:ExpeditionMissionKind// .sessionCount / .focusMinutes / .deepFocusCountlettargetValue:IntletrewardMiles:Int}``` 任务类型就三种:累计专注次数、累计分钟数、深度专注次数。全部完成解锁下一座城市。这个结构看着简单,但给用户的感知完全不一样——不是"你今天专注了50分钟",而是"你在东京飞行了50公里,解锁了雨夜任务"。 实现成本其实不高,每次 `focusSession` 结束时遍历一遍当前章节的 missionStates,更新 progress 值,判断是否触发 completedAt 就行了。 ## 统计和分享卡片:花了三周才搞定 战报卡片是我花时间最多的部分。每次专注结束要生成一张好看的卡片,包含时长、声景、效率指数、经验值增长。周末还有周回顾卡片,画7天分布图。ViewModel层我写得很薄,核心计算全部收在 `StatsService` 里: ```swiftvarstats:StatsData{StatsService.buildStatsData(focusLogs:logs,streakDays:store.streakDays,rangeKey:.d7,now:Date(),isDemo:store.focusLogs.isEmpty)}``` 这里有个取舍:当用户 focusLogs 为空时,我会塞 demo 数据进去。新用户打开统计页看到的不是空白,而是示例卡片。这样他知道"坚持几天后我也能得到这个"。试了不放 demo 数据的版本,新用户留存明显差一截。 卡片渲染这块踩了坑。一开始用SwiftUI直接转UIImage,部分机型偶现空白图。后来改成先塞进UIHostingController、等布局完成再截图,问题解决了但代码丑了不少。 ## 智能推荐下一次专注1.4版本加了一个功能:专注结束后根据历史数据推荐下一次的时间和时长。 逻辑考虑三个因素:今天日计划还差几段、当前连续天数、历史高频专注时段。连续天数不同,提示文案不同——连续5天以上说"重点是保持节奏",刚开始的用户说"先连续3天试试"。 这些文案我改了好几版。最早写得太鸡汤被我自己嫌弃了,太冷冰冰又没有推动力。最后的原则是:只说事实和建议,不说"加油你可以的"。 ## 灵动岛1.2版本接了ActivityKit做灵动岛显示。锁屏状态能看到剩余时间和当前声景名。ContentState里放了 endDate、phase、remainingSeconds、progress 这些字段。 这个功能实现不复杂,主要注意更新频率别太高就行。对用户体验提升挺明显——不用解锁手机就能瞄一眼还剩多久。 ## 踩过的坑和一些数字 上架时间:202412月。当前版本1.4。 说实话最近一周下载基本为零。独立开发没预算推广,冷启动全靠搜索和口碑,这事儿急不来。 几个教训:-声景音频文件把包体撑到了 200MB+,后来改按需下载才降到 60MB--成长系统经验值公式改了三次。第一版两天就满级,完全没有盼头。现在大概连续用两周到Lv.5--分享功能做得再花哨,如果用户没养成打开App的习惯,就没有分享的机会。所以通知策略比卡片设计更重要 ## 后续想法 在考虑做鸿蒙版本。ArkUI声明式写法和SwiftUI思路接近,ViewModel逻辑迁移应该不难。音频后台播放和卡片服务(对标LiveActivity)这块还在研究HarmonyOS的文档。 如果你也在做 iOS 或者鸿蒙的工具类独立应用,可以评论区聊聊,互相参考一下踩坑经验。AppStore搜索「声境护照」能找到。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 5:08:36

STK 11.6与Matlab 2022b互联保姆级教程:从安装到避开‘mexConnect’报错

STK 11.6与Matlab 2022b互联全流程指南:从环境搭建到实战避坑 在航天系统仿真与任务分析领域,STK(Systems Tool Kit)与Matlab的协同工作已成为行业标配。最新版本的STK 11.6与Matlab 2022b组合带来了更强大的计算能力和更丰富的接…

作者头像 李华
网站建设 2026/5/1 5:03:22

ARM GICv5中断控制器与IRS模块详解

1. ARM GICv5中断控制器架构概述中断控制器(Generic Interrupt Controller,GIC)是现代处理器系统中至关重要的组件,负责高效管理和分发硬件中断请求。作为ARM架构的标准中断控制器实现,GICv5在原有架构基础上引入了多项…

作者头像 李华
网站建设 2026/5/1 4:59:22

大模型赋能邻域搜索:G-LNS优化算法解析

1. 项目概述:当大模型遇上优化算法在运筹优化领域,邻域搜索算法一直是解决复杂组合优化问题的利器。而G-LNS这个项目将生成式大语言模型与传统的大邻域搜索(LNS)框架相结合,创造性地实现了启发式规则的自动设计。这就像…

作者头像 李华
网站建设 2026/5/1 4:58:24

移动WiMAX吞吐量测量技术与优化实践

1. Mobile WiMAX™吞吐量测量技术解析作为一名从事无线通信测试十余年的工程师,我深知吞吐量测量在移动WiMAX™(IEEE 802.16e)设备开发中的重要性。本文将基于R&SCMW测试平台的实战经验,深入解析从物理层到应用层的吞吐量测量…

作者头像 李华