独立开发一个健康记录 App,聊聊 SwiftData 数据建模和拨轮交互的踩坑过程
起因我爸的血压本快记满了去年过年回家看到我爸床头那个写满数字的小本子——每天早晚量血压用笔记下来密密麻麻的。翻了翻有些字迹已经模糊了有些日期明显漏记了最关键的是每次去医院医生问最近血压怎么样他就翻本子翻半天找不到。我当时就想这事儿我能用 App 解决。市面上血压记录的 App 不是没有但我试了七八个要么界面花哨功能一堆但录入贼慢要么是那种需要注册登录还要订阅的。我爸那个年纪打开 App 点三下还没输进去数字他就不愿意用了。所以我做了「健康手账」核心目标就一个让录入血压这个动作在 3 秒内完成。拨轮录入为什么不用数字键盘说实话最开始我是做了数字键盘输入的。标准做法嘛一个 TextField弹出数字键盘输入收缩压、舒张压、脉搏三个字段。但我拿给我爸试的时候他的操作是这样的点输入框 → 键盘弹出来挡住了下面的内容 → 输错了一位要删掉重来 → 输完第一个不知道怎么跳到第二个字段。整个过程大概要 20 秒。后来我换成了拨轮Picker wheel的方案。就像 iOS 原生的时间选择器那种感觉手指一拨数字就定了。收缩压、舒张压、脉搏三个轮并排放拨到位直接保存。实测下来熟练之后真的 3 秒能搞定。这个拨轮我没有用系统的Picker因为系统 Picker 的触感和阻尼不太对拨动的时候有点飘。我自己用ScrollViewGeometryReader实现了一个带物理阻尼感的拨轮加了scrollTargetBehavior(.viewAligned)来做对齐吸附。调手感这事儿花了我大概两周改了无数次阻尼参数。SwiftData 建模一条记录要存多少东西数据模型我用的是 SwiftDataiOS 17 之后苹果推的新持久化框架比 Core Data 写起来舒服太多。一条健康记录的结构长这样ModelfinalclassHealthRecord{varid:UUIDvartimestamp:Datevarsystolic:Int?// 收缩压vardiastolic:Int?// 舒张压varpulse:Int?// 脉搏varweight:Double?// 体重varnote:String?vartagIDs:[String]// 关联的状态标签varprofileID:Stringdefault// 多人档案init(timestamp:Date.now,systolic:Int?nil,diastolic:Int?nil,pulse:Int?nil,weight:Double?nil,note:String?nil,tagIDs:[String][],profileID:Stringdefault){self.idUUID()self.timestamptimestampself.systolicsystolicself.diastolicdiastolicself.pulsepulseself.weightweightself.notenoteself.tagIDstagIDsself.profileIDprofileID}} 几个设计决策说一下**所有指标都是Optional。**因为不是每次录入都要填全部字段。有时候只量血压有时候只称体重。强制要求填完所有项在我看来是反人性的。**profileID 做多人档案。**这个需求来自我自己——我想在一个App里同时记我爸和我妈的血压。用 profileID 做区分查询的时候加个 filter 就行比搞多个数据库简单得多。默认值是 default这样老版本升级上来的数据不会丢。**tagIDs 关联状态标签。**这个是后来加的功能。我发现光记血压数字不够还得知道当天有没有吃药、有没有运动、有没有喝酒。这些干预行为我做成了可自定义的标签叫状态印章。预置了降压药、减脂餐、运动、好睡眠、黑咖啡这几个用户可以自己加。 记录和标签之间用 tagIDs 数组做松耦合关联没有用SwiftData的Relationship。说实话这个选择有点取巧——Relationship在SwiftData早期版本iOS17.0有一些诡异的 bug数据偶尔会丢关联我被坑过一次之后就改用ID数组了。虽然查询的时候多一步但至少数据稳定。 ## iCloud 同步给了开关让用户自己选 数据同步这块我纠结了很久。 健康数据是隐私数据有些用户不想上云但有些用户换手机的时候又需要数据跟过来。最后的方案是在设置里给一个 iCloud 开关默认关闭用户手动打开才走CloudKit。 实现上ModelContainer 初始化的时候根据UserDefaults里的标记来决定 cloudKitDatabase 是 .automatic 还是 .none。这意味着切换开关后需要重启App才能生效——这个体验说实话有点粗糙但SwiftData的ModelContainer一旦创建就没法改配置我暂时没找到更好的办法。 ##PDF就医报告这个功能意外地受欢迎 做这个功能的契机是我陪我爸去看心内科。医生问最近血压情况我掏出手机给他看App里的趋势图。医生瞄了一眼说你能不能打印出来我要放病历里。回来我就做了PDF导出功能。选一个时间范围App自动生成一份排版好的报告患者姓名、时间段、血压统计平均值、最高最低、趋势折线图、每日明细表。格式参考了医院里那些检查报告的排版A4 纸打出来医生一看就懂。 这个功能上线后反馈比我预想的好。有个用户给我发邮件说他每次去看诊前都会导一份医生看了直接说这个挺好以后每次都带着。 ##Siri快捷指令语音触发录入 后来加了AppIntents支持用户可以通过Siri说用健康手账记录健康数据来直接打开录入界面。实现上就是定义一个 AppIntent设置 openAppWhenRuntrue然后通过NotificationCenter通知主界面弹出录入面板。 这个功能的使用频率说实话不高但对于每天固定时间测血压的用户来说配合快捷指令的自动化比如每天早上7点自动弹提醒体验还是不错的。 ## 提醒功能的小细节 提醒不是简单的每天X点推一条通知。我做了按星期几选择的功能——有些用户周末不想被打扰有些用户只有工作日才规律测量。reminderDays 存的是一个 SetInt1到7对应周日到周六和Calendar的 weekday 对齐。 每次App回到前台的时候会重新调度通知ReminderScheduler.reschedule确保修改设置后能立刻生效。 ## 现在的情况和一些想法App在2024年上架AppStore买断制不搞订阅。 说实话下载量不大健康记录这个品类竞争挺激烈的而且很多大厂的App都免费。但我做的时候就没想过要靠这个赚大钱能覆盖开发者账号的年费就行。我爸现在确实在用每天早晚各记一次这就够了。 对了我正在做HarmonyOS版本。鸿蒙的项目结构已经搭好了用的Hvigor构建但ArkUI的自定义组件能力和SwiftUI还是有差距特别是拨轮那个交互在ArkTS里要重新实现一遍还在摸索中。等鸿蒙版做出来了再单独写一篇聊聊跨平台的适配经验。 如果你也在做健康类App或者对SwiftData的实际使用有什么经验欢迎评论区聊聊。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2559424.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!