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

技术人差旅效率优化指南:从系统思维到实战技巧 在软件工程和系统架构中,我们常通过优化流程、管理依赖和提升资源利用率来改善系统性能。这一原理同样适用于技术人员的差旅场景。通过将出行视为一个可配置、可优化的系统,我们可以运用工程思维来提升其可靠性、资源利用率和舒适度。例如,通过创建详细的出行清单(Checklist as Code)来管理设备依赖,利用离线开发环境(如本地Git仓库和SQLite数据库)确保工作连续性,并采用时间块规划(Time Boxing)来高效利用飞行时间进行深度工作或学习。这些方法的核心价值在于将碎片化的交通时间转化为高价值的产出时 阅读详情

为什么要做这个App

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

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

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

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

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

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

struct ExpeditionChapterDefinition: Identifiable, Codable, Equatable {
    let id: String
        let sceneId: String
            let cityName: String
                let tagline: String
                    let bonusBounces: Int
                        let missions: [ExpeditionMissionDefinition]
                        }
struct ExpeditionMissionDefinition: Identifiable, Codable, Equatable {
    let id: String
        let title: String
            let kind: ExpeditionMissionKind  // .sessionCount / .focusMinutes / .deepFocusCount
                let targetValue: Int
                    let rewardMiles: Int
                    }
                    ```
任务类型就三种:累计专注次数、累计分钟数、深度专注次数。全部完成解锁下一座城市。这个结构看着简单,但给用户的感知完全不一样——不是"你今天专注了50分钟",而是"你在东京飞行了50公里,解锁了雨夜任务"。

实现成本其实不高,每次 `focusSession` 结束时遍历一遍当前章节的 missionStates,更新 progress 值,判断是否触发 completedAt 就行了。

## 统计和分享卡片:花了三周才搞定

战报卡片是我花时间最多的部分。每次专注结束要生成一张好看的卡片,包含时长、声景、效率指数、经验值增长。周末还有周回顾卡片,画7天分布图。

ViewModel 层我写得很薄,核心计算全部收在 `StatsService` 里:

```swift
var stats: 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 这些字段。

这个功能实现不复杂,主要注意更新频率别太高就行。对用户体验提升挺明显——不用解锁手机就能瞄一眼还剩多久。

## 踩过的坑和一些数字

上架时间:2024年12月。当前版本 1.4。

说实话最近一周下载基本为零。独立开发没预算推广,冷启动全靠搜索和口碑,这事儿急不来。

几个教训:

- 声景音频文件把包体撑到了 200MB+,后来改按需下载才降到 60MB
- - 成长系统经验值公式改了三次。第一版两天就满级,完全没有盼头。现在大概连续用两周到 Lv.5
- - 分享功能做得再花哨,如果用户没养成打开 App 的习惯,就没有分享的机会。所以通知策略比卡片设计更重要
## 后续想法

在考虑做鸿蒙版本。ArkUI 声明式写法和 SwiftUI 思路接近,ViewModel 逻辑迁移应该不难。音频后台播放和卡片服务(对标 Live Activity)这块还在研究 HarmonyOS 的文档。

如果你也在做 iOS 或者鸿蒙的工具类独立应用,可以评论区聊聊,互相参考一下踩坑经验。

App Store 搜索「声境护照」能找到。

相关推荐

深入NAND Flash信号与接口:结合ONFI 5.0协议,聊聊DBI、ODT和差分信号到底在解决什么实际问题

本文深入探讨了NAND Flash信号与接口设计,结合ONFI 5.0协议,详细解析了DBI、ODT和差分信号等技术如何解决高速数据传输中的信号完整性问题。通过实际案例和数据,展示了这些技术在降低功耗、减少噪声和提升抗干扰能力方面的显著效果,为存储工程师提供了宝贵的实践参考。

weixin_33736649的博客 341

GPT-4o生活实用技巧:普通人可立即上手的AI协作者指南

大语言模型不是万能工具,而是需要被精准指挥的智能协作者。理解其本质——基于概率的语言生成系统而非知识库——是高效落地的前提。GPT-4o与GPT-4 Turbo已具备长上下文、多模态理解与毫秒级响应能力,技术水位足以支撑80%日常决策、表达、学习与事务管理场景。关键不在等待更强模型,而在于掌握‘角色设定+结构化指令+分步验证’这一人机协作范式。本文聚焦真实生活断点:从微信语音摘要、合同风险扫描到孩子作业归因、家庭采购归类,所有技巧均满足可感知(5分钟见效)、可中断(支持碎片操作)、可验证(答案有据可查)三大

Envisage123 422

【FPGA】高效捕捉信号边沿的硬件实现技巧

本文深入探讨了FPGA设计中高效捕捉信号边沿的硬件实现技巧。核心在于通过“打两拍”同步器处理亚稳态风险,并详细解析了上升沿、下降沿及双边沿检测的基础原理与Verilog实现。文章进一步介绍了脉冲展宽、数字滤波等高级优化方案,并结合UART起始位检测与按键消抖等实战场景,提供了可靠的代码范例与调试心得,帮助工程师构建稳定可靠的边沿检测模块。

weixin_29165465的博客 225

iOS 多语言本地化教程,VS Code KXApp 编辑 String Catalog .xcstrings

做 iOS 多语言本地化总要在 VS Code 和 Xcode 之间来回切?这篇讲用 KXApp(快蝎)在 VS Code 里直接编辑 String Catalog(.xcstrings):双击打开和 Xcode 一样的表格,`.xcstrings` 与老的 `.strings`、`.stringsdict` 同表编辑,加语言同步登记到工程、从源码扫描同步新 key,复数、设备变体和变量占位都在表里处理,改源语言文本后已有翻译自动标需复核。文件仍是标准格式,回 Xcode 打开一致。

2501_91592143的博客 154

SAP 接口测试操作-业务顾问

业务顾问测试接口操作

weixin_43657667的博客 5156

Linux下搭建J-Link调试环境:OpenOCD+GDB实战指南

嵌入式开发中,调试器是连接开发主机与目标硬件的关键桥梁,其核心原理是通过标准协议(如JTAG/SWD)访问芯片内部的调试模块。GDB作为通用的调试客户端,通过远程协议与调试服务器通信,而OpenOCD则扮演了协议转换与硬件驱动的角色,实现了调试命令的翻译与执行。这种开源工具链的组合,为开发者提供了高度的定制化与自动化能力,尤其适合需要与持续集成流程深度结合的复杂项目。在实际应用中,针对特定芯片(如ARM7TDMI)进行正确的内存控制器与时钟初始化是成功调试的前提,这常常涉及对板级支持包的深入理解。本文以S3

weixin_29889665的博客 333

4G 功能机操作系统选型指南:KaiOS、Mocor、MAUI、PMAOS 的能力边界与验证方法

4G 功能机如何选择操作系统?本文梳理 KaiOS、Mocor、MAUI、PMAOS 四条路线的技术定位与能力边界,从市场认证、应用清单、芯片与 BSP、内存与整机成本、交付维护五个维度建立选型流程,并提供场景决策矩阵和签约前八项验证清单,帮助研发与产品团队区分平台宣称、演示能力与目标机型的实际交付能力。

PMAOS的博客 182

基于 Langchain 开发一个完整的支持多轮数据分析(直连 mysql 数据,多表综合分析 SQL 取数,数据分析,报表生成)ChatBI 系统(前后端完整实现源代码)

ChatBI系统开发摘要 本文介绍了基于Langchain的多轮数据分析ChatBI系统开发方案。该系统支持MySQL数据库连接,提供多表分析、SQL查询、数据分析和报表生成功能。系统采用前后端分离架构:前端使用React+Ant Design+ECharts实现交互界面;后端基于FastAPI搭建服务,集成Langchain处理自然语言到SQL的转换;核心技术栈还包括SQLAlchemy、Pandas和Matplotlib。 系统核心模块包括: 数据库连接层:使用SQLAlchemy管理MySQL连接 L

AI天才研究院 812

iOS 小组件开发,Windows 上用 KXBuild 加 WidgetKit 扩展 给 App 加 iOS 桌面小组件

iOS 小组件开发用 WidgetKit。这篇在 Windows 上用 KXBuild 的 add-target --type widget 给 SwiftUI 工程加一个桌面小组件扩展:写时间线和主屏小号/中号、锁屏圆形多种尺寸界面,用 App Group 和 App 共享数据,App 里调 WidgetCenter 主动刷新,按 F5 装到 iOS 17+ 的 iPhone 调试,再随 ipa 一起上架。以喝水打卡为例,附 App ID、描述文件准备和小组件不刷新、签名报错的排查。

2501_91600747的博客 181

SPI为什么不需要加上拉电阻

大家好,我是记得诚。I2C因为其开漏的结构,无法输出高电平,所以外部加上拉电阻。我们在使用SPI的时候,发现是不需要加上拉电阻的。主要因为SPI多为推挽的结构,推挽电路,高低电平都可以输出,所以外部不需要加上拉电阻。推挽电路可以用2个三极管或者2个MOS管搭建而成。

记得诚 2619

【系统架构设计师-2024下半年真题】案例分析-参考答案及部分详解(完整回忆版)

根据h中描述,为了保证高可靠性,有ping/echo,心跳机制两种策略,从资源利用率问为啥心跳更好。王工觉得使用ping/echo好,但李工觉得从系统资源利用率来说,使用心跳机制好 1、针对质量属性可以使用ping/echo和心跳模式实现,分别简述ping/echo和心跳的实现原理。 2、张工认为心跳策略比较适合,简述为什么?

数据知道的博客 1万+

React Native项目开发(iOS侧为例)

本文基于React Native 0.71+,通过npx react-native init初始化项目后,详细讲解如何使用TypeScript搭建两个页面:入口页(Entrance.tsx)和我的页面(Profile.tsx)。重点介绍了配置tsconfig.json、初始化TypeScript环境、集成React Navigation实现页面跳转,并通过创建共享类型文件(navigation.ts)实现路由类型安全。文章还涵盖依赖安装、iOS构建问题排查、目录结构规范及常见错误解决方案。

D_xw_的博客 232

pytorch搭建SSAE实现预测分类代码模板完整代码

pytorch搭建SSAE实现预测分类代码模板完整代码

323

安卓IOS打包证书

.p12 、 .mobileprovision 、 keystore 相关证书申请

weixin_58431406的博客 273

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

iOS 推送通知怎么实现,从 APNs p8 密钥到 iOS 真机收到第一条推送

iOS 推送通知要跑通,核心是 App ID 开通 Push Notifications 并重新生成描述文件、签名带上 aps-environment、再用 APNs 的 .p8 密钥签 JWT 把推送发到设备令牌。这篇用 KXBuild 按五步做:开能力、加 entitlements、代码里请求权限拿设备令牌、建 .p8 认证密钥、用一段 Node 脚本或 curl 走 HTTP/2 发测试推送,让 iPhone 弹出第一条通知。附拿不到令牌、APNs 报错码、TestFlight 收不到的排查。

2501_91591841的博客 219

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

[iOS]Runtime2

为了让你在父类中依然能访问当前对象(也就是子类的实例),编译器在底层会生成一个结构体,叫 : 当调用 时,底层调用的函数是 : 拿着(也就是当前的子类对象)作为消息接收者,但是把方法查找的起点定位在了 (父类)这里需要注意的就是仍然是调用者自己,即先讲一下上篇没讲过的,我们如果缓存未命中,那我们就会进入慢速查找,现在我们来详细的讲解在进入慢速查找的瞬间会再看一遍方法列表,然后立刻调用加锁,因为多线程下别人正在动态添加方法或者扩容,不加锁会崩溃类就绪OC的机制就是在编译期只生成了 结构,当类首次被发送消息时(

wzm20070304的博客 214

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

iOS App 图标、启动屏和多语言搭配 方法,上架前使用KXBuild一次做好 App 图标

上架前,iOS 的 App 图标、启动屏和多语言这三样配不齐,上传时就可能被拦或显示不对。这篇用 KXBuild 一次配好:图标只要一张 1024×1024、不带透明通道的 PNG,在资源目录编辑器里右键就生成全部尺寸,还支持 iOS 18 深色/着色和 Xcode 26 的 .icon;启动屏在 Info.plist 的 UILaunchScreen 填背景色和 Logo;界面文字、App 名称用 .xcstrings 翻译,商店信息再到 App Store Connect 按语言填。附上架前检查清单。

2501_91600889的博客 274

Appuploader 创建 iOS 描述文件详解,Development / Ad Hoc / App Store

搞不清 iOS 描述文件(Provisioning Profile)该选 Development、Ad Hoc 还是 App Store?本文讲清四种类型各装到哪、哪些要绑设备、能不能上架,重点辨析最容易混的 Development 与 Ad Hoc,说明设备或证书变动后为什么要重建、重建后要重新导入签名,并给出不用 Mac 在 Windows/Linux 上用 Appuploader 新建与重建描述文件的实操步骤,附装机"描述文件不匹配"等常见问题排查。

2501_91373349的博客 214

Windows 开发 iOS,Sign in with Apple 苹果登录,KXBuild 真机调试全流程

Sign in with Apple 接入分四步:App ID 开能力并重新生成描述文件,entitlements 加 com.apple.developer.applesignin,用 SignInWithAppleButton 拿 identityToken 交服务端验签,删账号时调 revoke。本文讲清审核指南 4.8 为什么要你提供它、姓名邮箱只给一次、用 user 当主键,并在 Windows 上用 KXBuild 真机测登录,附 1000 报错排查。

2501_91373349的博客 203

iOS 深度链接配置教程,URL Scheme 与 Universal Links,KXBuild 真机验证

深度链接两种:URL Scheme(myapp://)只改 Info.plist 的 CFBundleURLTypes;Universal Links(https://)要开 Associated Domains、在 entitlements 写 applinks 域名、网站放 /.well-known/apple-app-site-association。讲清两者怎么选、onOpenURL 处理代码,在 Windows 上用 KXBuild 装 Debug 包真机验证,附 CDN 缓存和十个不跳转排查。

2501_91600747的博客 260

手机远程控制电脑哪家强?2026年iOS/安卓/鸿蒙横评实测,ToDesk/向日葵谁更流畅

手机远程控制电脑已成刚需,ToDesk凭借全平台覆盖、低延迟、无广告、免费不限速等优势,成为最佳选择。其iOS、安卓、鸿蒙及Mac系统均支持,实测连接快、操作流畅,虚拟键盘、外接键鼠、互动批注等功能体验出色。相较之下,向日葵存在限时踢线、传输慢、广告多等痛点。选购建议:无论用何种手机,首选ToDesk,实现高效便捷的远程办公与协助。

lx08113的博客 270

Cocos Creator3.8.8 + Xcode27.2 编译运行失败

Cocos Creator3.8构建IOS工程后,使用最新的Xcode27.2版本进行真机调试,遇到C++标准库冲突,如is_floating_point、is_arithmetic和is_signed失败,以及webp对齐失败等问题。

HYNN12的博客 302

go消息推送之极光推送 (JPush REST API + SDK,覆盖安卓与iOS)

使用 gorush有个绕不开的问题:国内安卓设备上 FCM 基本不可达,华为、小米、OPPO、vivo 各自为政——此时可用极光推送(JPush)作解决方案。它的思路和前面几家都不一样:App 集成极光 SDK 后拿到统一的 RegistrationID,服务端发一条 REST 请求,极光云端自动把消息路由到 APNs、各家厂商通道或极光自有长连接。这里给出了:一个用纯标准库直接调用极光的;另一个用社区维护的,类型化参数,接口注释与官方文档逐条对应。两个功能相同,可放在一起对比学习。

qq_40467670的博客 157

华为昇腾910B4(A2)服务器环境搭建笔记

Qwen3.5 默认支持思考模式。首次测试建议关闭思考模式,更容易判断模型是否成功回答。我建议把模型统一存放在宿主机的 /data/models 目录中。这样即使删除 Docker 容器,模型文件也不会丢失。这里先进行单卡测试,确保容器能正确调用 NPU。安装ModelScope 用于下载模型。继续在刚才的容器内部执行。

guoqingru0311的博客 287

IPD咨询洞察:华为项目文化:让胜利成为一种信仰

华为“让胜利成为信仰”的本质是使命必达,落地为五项内核:开放创新、勇于担当、团队协同、契约精神、善思善结。使命必达不能停留在墙面标语,须转化为可落地、可考核的行为准则,胜利才能真正成为团队习惯。

weixin_58096508的博客 92

手头只有华为配置,新设备是华三?粘进来自动翻

手头有华为配置,新设备是华三?用「跨厂商转换」工具,粘贴配置后自动识别源厂商,一键转成目标厂商语法,支持华为、华三、锐捷、迈普、思科等主流设备。精准处理VLAN、access/trunk口、SVI IP、VTY/SSH等差异,避免手动修改时漏改“拼写级”错误。转换后需人工核对核心项与独有特性,建议结合备份、比对与模拟验证,确保安全上机。

qq_42614669的博客 382
上一篇: 从SwiftData到鸿蒙relationalStore:移植一款精力管理App的三周踩坑记
下一篇: 我用 ArkTS 做了个精力管理 App,把自己当电池来记录状态
SameX-4869
博客等级 码龄17年 3354粉丝 657原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值