爱意满满的作品展示区。
MagicCoder

开发了一个进阶版 Apple 健康

  •  1
     
  •   MagicCoder · 3 days ago · 3834 views

    前言

    使用 iPhone + Apple Watch 组合有段时间了,当初买的时候,想着用它来记录我的跑步数据,但是坚持了没多久,我就懒惰了,手表最大的作用就成了睡眠监测工具了,由于作息一直比较规律(晚 11 ~早 7 ),就没怎么关注过这些。

    最近半年时间,时不时的熬夜写开源项目,我开始关注自己的健康状况了,打开系统自带的的健康 app 把玩了一番,发现它的数据特别全,但是有几个不好用的地方:

    • 首页的内容比较分散,指标都是以列表的形式进行展示的
    • 指标层级较深,需要切来切去,很多指标我更希望将他们展示到一个大的分类里
    • 指标太单一,大多数时候我并不是只想看某个数据,而是把睡眠、恢复、心率、压力、活动放在一起看,给出更完整的身体状态视角。
    • Apple 只会在你静息心率过高的时候给你发出提醒,而我日常会更关心“最近状态怎么样?哪里变好了?哪里需要注意?”

    IMG_4989

    寻找替代品

    Apple Watch 的销量这么好,肯定不止我一个人觉得自带的软件不好用的。经过一番查找后,找到了几个看着还不错的,把他们都下载下来体验了下,综合下来给我的感觉是:

    • 功能做的太多了,我一眼看过去有点恍惚,接下来我该点什么?
    • 界面做的太卡通了,我比较喜欢简约风格的东西,更贴近系统的设计风格

    自己开发

    体验了 5 款这类软件,始终没找到适合我的,那就只能花点时间开发一个了⚒️

    产品设计

    我给这个应用取名为 VirPulse ,它并不是想取代 Apple 健康,而是把 Apple 健康里已经记录好的数据重新整理一遍,让我能更快看懂自己的状态。

    在设计产品时,我先给自己定了一个原则:不要把 Apple 健康里的所有数据重新抄一遍,也不要一打开软件就塞给用户几十个指标。

    所以整个软件只保留了 3 个主要入口:

    • 首页:快速看懂今天的状态
    • 分析:把多个指标放在一起看
    • 搜索:直接找到某个具体指标

    可能很多人会好奇,为什么这个应用叫VirPulse

    我的上一个作品叫NginxPulse,它将 Nginx 访问日志转换成直观的图表,就像在查看 Nginx 的“生命体征”一样。

    健康数据记录的是一个人每天的身体状态,而心跳又是生命最直接的信号,所以我还是想保留 Pulse 这个词。

    一开始本来想叫 LifePulse ,但是 App Store 里已经有了同名应用。后来我继续从生命力、力量相关的词里寻找灵感,最终从拉丁语Virtus中取了前面的Vir,再和Pulse组合,于是就有了VirPulse这个名字。

    首页

    首页是我每天打开次数最多的地方,所以这里没有放太多复杂的图表,而是先给出一个今日状态评分,再展示睡眠、静息心率、HRV 、步数和活动消耗等信息。

    这个评分不是简单取某一个指标,而是会结合睡眠恢复、身体恢复、活动完成度以及最近一段时间的变化趋势进行计算。

    比如昨晚睡眠时间不够、HRV 下降、静息心率又比平时高,那么软件就会提醒我最近可能需要多休息,而不是只展示几个冷冰冰的数字。

    IMG_4927

    这里的评分主要用于观察个人趋势,不作为医疗诊断。

    分析

    分析页是这个软件的核心功能,我把健康数据分成了运动、睡眠、代谢和压力几个大的分类。

    IMG_4928

    每个分类都不是只看一个数据,例如睡眠分析会同时参考:

    • 睡眠时长和睡眠阶段
    • 入睡、起床时间是否规律
    • 夜间心率和 HRV
    • 血氧、呼吸频率和腕温

    压力状态也不是手表直接提供的数据,而是结合睡眠变化、HRV 、静息心率、活动节律等数据进行估算。

    image-20260622024136831

    时间范围支持近 7 天、近 30 天、近 90 天和自定义日期,可以用来判断某个变化是偶尔出现,还是已经持续了一段时间。

    如果某些数据缺失,软件不会简单按 0 分计算,而是只使用当前已有的数据,并提示这次分析的依据是否完整。

    趋势和搜索

    有时候我并不想看综合分析,只是想确认某个具体指标最近有没有变化,所以做了一个搜索入口。

    IMG_4990

    在这里可以直接搜索睡眠、心率、HRV 、血氧、体重、体脂、腕温等指标。点进去后,可以查看最近记录、平均值、最高值、变化趋势以及这个指标和其他健康状态之间的关系。

    IMG_4991

    IMG_5076

    IMG_5077

    首次连接 Apple 健康时,会先同步最近 90 天的数据,之后再在后台补全近 400 天的历史趋势。

    小组件

    为了减少打开软件的次数,我还做了多套桌面小组件,可以直接查看今日状态、睡眠评分、活动进度、压力状态和生命体征趋势。

    同时也适配了待机显示,晚上给手机充电时,就可以把它当成一个简单的健康状态面板。

    IMG_4933

    界面风格

    界面上没有加入太多卡通元素,整体以深色背景、半透明卡片和系统图标为主,不同颜色只用来区分睡眠、心率、活动等指标。

    image-20260622024656545

    页面切换、下拉刷新、图表拖动和底部 Tab 也尽量遵循 iOS 原生的交互方式,用起来不会有太强的学习成本。

    IMG_4931

    image-20260622024943489

    数据隐私

    健康数据比较敏感,所以 HealthKit 读取到的原始数据、趋势和分析结果都保存在设备本地,相关计算也是在本地完成的。

    服务端主要用于 Apple 账号登录、用户资料和会员状态,不会上传每天的睡眠、心率、步数这些健康记录。

    技术栈

    这是一个原生 iOS 项目,最低支持 iOS 17 ,并针对 iOS 26 的新 Tab 和 Liquid Glass 系统进行了深度适配。

    客户端全部使用 Apple 官方提供的框架,没有引入第三方 UI 和数据处理库,主要技术栈如下:

    • SwiftUI:负责整个软件的界面和交互
    • HealthKit:读取 Apple 健康中的睡眠、心率、HRV 、活动等数据
    • SwiftData:在本地保存健康数据、分析结果和趋势缓存
    • Swift Charts:绘制趋势图、睡眠阶段和指标详情图表
    • WidgetKit:实现桌面小组件和待机显示
    • StoreKit 2:处理月付、年付、永久买断、恢复购买和兑换代码
    • AuthenticationServices:实现通过 Apple 登录
    • URLSession + async/await:和后端接口进行通信
    • Keychain:保存登录令牌

    首次授权时读取最近 90 天数据,后续按天增量同步,同时在后台分批补全近 400 天历史数据。这样既不会让第一次进入软件等待太久,也能保留足够长的趋势数据。

    图表数据比较多时,如果直接在页面切换过程中读取和计算,会明显感觉到卡顿。所以详情页会先打开一个轻量页面,再异步准备数据,等页面切换完成后再挂载图表。

    业务实现主流程:

    3333

    服务端是基于我现有的 Java 项目继续开发的,主要技术栈如下:

    • Spring Boot + Java:提供账号和会员相关接口
    • MyBatis + MySQL:保存用户资料、登录令牌和订阅记录
    • JWT:处理访问令牌和刷新令牌
    • App Store Server API:校验 Apple 交易和会员状态
    • App Store Server Notifications:接收续订、过期和退款等订阅变化

    健康分析并不依赖服务端,服务端主要负责确认“这个用户是谁”和“这个用户是否拥有 Pro 会员”。即使网络暂时不可用,已经同步到本地的健康数据依然可以正常查看。

    获取应用

    VirPulse 现已在全球 App Store 上架,打开 App Store 搜索“VirPulse”即可下载。

    IMG_4992

    写在最后

    至此,文章就分享完毕了。

    我是神奇的程序员,一位前端开发工程师。

    如果你对我感兴趣,请移步我的个人网站,进一步了解。

    Supplement 1  ·  1 day ago

    用户交流群

    IMG_5223

    45 replies    2026-06-27 15:30:43 +08:00
    GoogolChrome111
        1
    GoogolChrome111  
       3 days ago via iPhone
    已下载,点赞
    xy2401
        2
    xy2401  
       3 days ago
    居然有服务端吗。我还以为就是读取 apple 数据做一个界面展示的 app
    MagicCoder
        3
    MagicCoder  
    OP
       3 days ago
    @xy2401 对,做了服务端的,我做软件喜欢做到极致🤣
    MagicCoder
        4
    MagicCoder  
    OP
       3 days ago
    @GoogolChrome111 登陆后还有个抽奖活动的,随机发放永久、年度、月度会员
    CLOUDUH
        5
    CLOUDUH  
       3 days ago
    提个建议哦,移动网络和 Wi-Fi 的权限应该在登录之前获取,不然会登录失败一次。
    Lin0936
        6
    Lin0936  
       3 days ago
    iOS27 HealthKit 有改动,首次请求权限时默认只给近 30 天的数据
    jonsonk
        7
    jonsonk  
       3 days ago via Android
    体验很棒,已经用上了。能增加表盘样式或把桌面小组件的样式添加到表盘就更好了。
    MagicCoder
        8
    MagicCoder  
    OP
       3 days ago
    @jonsonk 嗯嗯 我后面开发这功能
    MagicCoder
        9
    MagicCoder  
    OP
       3 days ago
    @Lin0936 哦哦哦 这样,我晚点适配下
    MagicCoder
        10
    MagicCoder  
    OP
       3 days ago
    @CLOUDUH 奇怪了,我设置的在第一个步骤就请求网络权限了
    Ealrang
        11
    Ealrang  
       3 days ago
    支持一下,抽了个年度会员哈哈哈
    erquren
        12
    erquren  
       3 days ago
    这个数据是不是能直接用 icloud 存,不用放到服务端
    MagicCoder
        13
    MagicCoder  
    OP
       3 days ago
    @erquren 是的,不过我现在没存储用户的这些健康数据,全部放用户本地的,icloud 也没放。我的服务器只放用户的苹果 id 、昵称、头像这些,用来鉴权的
    GoogolChrome111
        14
    GoogolChrome111  
       3 days ago via iPhone
    @MagicCoder 谢谢你。我抽到年度会员
    Litchi824
        15
    Litchi824  
       2 days ago
    支持, 已下载, 抽到了一个月会员
    粗看了一下数据展现得很清晰明了(对比 AutoSleep), 打算继续体验一段时间

    遇到一个问题, 兑换会员码的时候卡在界面了, 只能强制退出重新进, 然后点几下就又卡着了~(iPhone air)
    mankismi
        16
    mankismi  
       2 days ago
    支持一下,另外回报个问题,因为手机是繁体,于 app 内设置语言切换无效,需要到系统设置那边设定语言
    另外求个繁体中文~
    MagicCoder
        17
    MagicCoder  
    OP
       2 days ago   ❤️ 1
    @Litchi824 行,我今晚修复下这个兑换问题
    MagicCoder
        18
    MagicCoder  
    OP
       2 days ago
    @mankismi 目前只支持简体中文和英文,后面我弄下😂
    keyileba
        19
    keyileba  
       2 days ago via iPhone
    已下载,感谢创造分享
    gotOwt
        20
    gotOwt  
       2 days ago
    老哥的工作学习态度真的是值得学习。。
    我现在已经摆烂了。。
    从掘金那时候认识你, 一晃你还在学习。。
    加油
    keyileba
        21
    keyileba  
       2 days ago via iPhone
    反馈:会有 Apple watch 的小组件吗?比如 hrv 曲线图或者其他总览之类的?或许可以参考同类 app 。
    lifeintools
        22
    lifeintools  
       2 days ago
    支持一下
    russ44
        23
    russ44  
       2 days ago
    已下载, 在应用内修改语言只能改一部分
    Webpoplayer
        24
    Webpoplayer  
       2 days ago
    已下载使用,抽中一次月费
    elboble
        25
    elboble  
       2 days ago
    以安装,申请了会员。

    不过我不喜欢戴表睡觉,所以没有睡眠数据,其他资料挺好
    MagicCoder
        26
    MagicCoder  
    OP
       2 days ago
    @keyileba 后面会开发 Apple watch 端
    wonderfulcxm
        27
    wonderfulcxm  
       2 days ago via iPhone
    哥们,你这静息心率有点高了!
    tyhunter
        28
    tyhunter  
       2 days ago
    感谢,抽到了一个年度会员
    MagicCoder
        29
    MagicCoder  
    OP
       2 days ago via iPhone
    @wonderfulcxm 现在软件上线了,我可以好好休息了😂 这个软件用了一个月的下班时间写的,天天干到凌晨 2 点,周六日猛猛睡
    wonderfulcxm
        30
    wonderfulcxm  
       2 days ago via iPhone
    @MagicCoder 心血之作啊,加油
    hayhong123
        31
    hayhong123  
       2 days ago
    支持一下 抽中了个永久会员
    muayang
        32
    muayang  
       2 days ago
    感谢创造,下载了 抽中了个永久会员
    SingeeKing
        33
    SingeeKing  
    PRO
       2 days ago
    我竟然中了 Lifetime !感谢
    StevenLx
        34
    StevenLx  
       2 days ago via iPhone
    英文版本下,很多内容还是中文显示的
    ChasenDai
        35
    ChasenDai  
       2 days ago
    抽到了年度会员,狠狠支持
    zaitaoxiaoairen
        36
    zaitaoxiaoairen  
       2 days ago
    MzU5OTc2ODI1QHFxLmNvbQ==
    感谢
    daiisdai
        37
    daiisdai  
       2 days ago
    UI 是怎么设计的呢?感觉挺简洁的
    MagicCoder
        38
    MagicCoder  
    OP
       2 days ago
    @daiisdai 找朋友帮忙弄的
    J3fFury
        39
    J3fFury  
       1 day ago
    设计很漂亮, 感觉有 Grow 内味了
    报个小 bug, 底部 toolBar 切换的过程 icon 底部会有奇怪的背景色
    iOS 26.5.1, 应该和设备型号无关
    MagicCoder
        40
    MagicCoder  
    OP
       1 day ago
    @J3fFury 方便贴个图吗?我排查下
    yametee
        41
    yametee  
       1 day ago
    抽到永久会员,感谢 OP
    MagicCoder
        42
    MagicCoder  
    OP
       1 day ago
    @yametee 恭喜,运气可以🤣
    MagicCoder
        43
    MagicCoder  
    OP
       1 day ago
    @zaitaoxiaoairen 已发送
    jiezou
        44
    jiezou  
       1 day ago
    很不错 已抽一个月会员
    brofen
        45
    brofen  
       21h 19m ago
    感恩,抽到永久会员。
    提 2 个建议:
    1 、分析 tab 页滚动掉帧比较明显。看看能否优化。
    2 、是否考虑出个 watch 端,显示心率、hrv 之类的数据。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2849 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 134ms · UTC 04:50 · PVG 12:50 · LAX 21:50 · JFK 00:50
    ♥ Do have faith in what you're doing.