当前位置: 首页 > news >正文

iOS拨轮交互实现:UIScrollView吸附+Haptic Feedback,3秒录入血压数据

起因:给我爸做一个能用的血压记录工具

去年我爸确诊高血压,医生让每天记录。试了七八个 App,要么界面复杂老人不会用,要么每次录入要点太多下。有一次他直接拿纸笔记了,复诊时掏出一张皱巴巴的纸条递给医生。

我当时就决定自己做一个。做出来叫「健康手账」,iOS 上架快半年了,版本 1.1。核心就解决两件事:录入太慢、数据到了手机里医生看不到。

拨轮交互:UIScrollView + 吸附 + Haptic Feedback

这是我花时间最多的地方。数字键盘录入血压太慢了——高压、低压、心率三个值,每个都要点三四下,老人容易按错还得删。

我的方案是模拟物理转盘的阻尼感,用 UIScrollView 做环形滚动区域,通过自定义吸附逻辑实现「转到哪停到哪」:

funcscrollViewWillEndDragging(_scrollView:UIScrollView,withVelocity velocity:CGPoint,targetContentOffset:UnsafeMutablePointer<CGPoint>){letcellHeight:CGFloat=44.0lettargetY=targetContentOffset.pointee.yletsnappedY=round(targetY/cellHeight)*cellHeight targetContentOffset.pointee.y=snappedY// 触觉反馈,模拟刻度感UIImpactFeedbackGenerator(style:.light).impactOccurred()}``` 加了HapticFeedback之后,转动时有轻微震动,我爸说「跟拧收音机一样」。实测录一条血压(高压+低压+心率)大概3秒,比键盘快3-4倍。 试过三种方案才定下来:UIPickerView太丑定制性差;CollectionView横向滚动手感不对;最后用竖向ScrollView+吸附才满意。中间删了两千行代码。 ##PDF就医报告:UIGraphicsPDFRenderer+自动分页 这个功能的场景很具体——我爸每次复诊,医生问「最近血压怎么样」,他就说「还行」。我想让他直接递一张纸给医生,上面有趋势图和表格。 技术上用UIGraphicsPDFRenderer渲染,难点在分页——数据多了表格要自动换页,行不能从中间截断。核心判断逻辑大概是这样: ```swiftfuncrenderTableRows(_rows:[RowData],incontext:UIGraphicsPDFRendererContext){varcurrentY:CGFloat=pageMarginTopforrowinrows{letrowHeight=calculateHeight(for:row)// 剩余空间不够一整行,强制换页ifcurrentY+rowHeight>pageHeight-pageMarginBottom{context.beginPage()currentY=pageMarginTopdrawTableHeader(at:&currentY)// 新页重绘表头}drawRow(row,at:&currentY)}}``` 关键是换页后要重绘表头,不然医生翻到第二页看不懂列代表什么。上次复诊医生扫了一眼说「这个整理得清楚」,算是验证了方向。 ## 多人档案:CoreData用 parent entity 隔离数据 支持建多个档案,我手机里有三个:我爸、我妈、我自己。 数据层用CoreData,多档案隔离的方式是在 schema 里加了一个 `Profile` entity 作为 parent,所有的 `BloodPressureRecord`、`WeightRecord`、`StatusStamp` 都通过 relationship 挂在某个Profile下面。查询的时候用NSPredicate按 profile 过滤: `NSPredicate(format:"profile == %@",currentProfile)` 没用多个 persistent store 的方案——太重了,而且将来如果做导出功能,单个SQLite文件比较好处理。 所有数据存在本地,没有服务器没有账号。健康数据太敏感,我不想碰用户隐私,也不想维护后端。代价是没法跨设备同步,但对于「每天固定用一台手机记录」的场景够用。 ## 状态印章:离散事件和时间序列数据的关联 除了数值记录,做了一组状态印章——吃药、运动、饮酒、熬夜。每天点一下,像盖章。 数据模型上,`StatusStamp` 是独立 entity,字段很简单:`type`(枚举)、`timestamp`、`profile`。它和 `BloodPressureRecord` 没有直接 relationship,关联展示是在趋势图渲染时按时间轴做的——取当天的所有 stamp,在折线图对应日期的X轴位置画小图标。 这样做的好处是 stamp 和数值记录完全解耦,将来加新的 stamp 类型不需要动血压/体重的 schema。坏处是查询「吃药日 vs 未吃药日的血压均值对比」时要在内存里做 join,数据量大了可能有性能问题——不过对于个人用户,几年的数据量也就几千条,目前没遇到瓶颈。 ## 目前状态-2024年上架,当前版本1.1--买断制,不搞订阅。慢病记录这种东西用户可能用好几年,订阅不公平--下载量说实话不多,没怎么推广过--日活不高但留存还行——毕竟是每天都要用的工具--鸿蒙版在计划中,ArkUI写数据录入界面应该挺合适 ## 一个想讨论的问题 做这种长期记录类工具App,你们会选CoreData还是SQLite(比如GRDB/FMDB)? 我选CoreData主要因为和NSFetchedResultsController配合做列表刷新很省事,iCloud 同步将来也有现成方案。但也遇到了烦心事——轻量级迁移(lightweight migration)在加新 entity 时没问题,改字段类型就容易翻车,有一次测试阶段数据全丢了。如果用SQLite自己管 schema 版本,至少迁移逻辑是透明可控的。 你们怎么选的?有没有踩过类似的坑?
http://www.jsqmd.com/news/731314/

相关文章:

  • RVC变声器终极指南:10分钟打造专业AI音色的完整教程
  • DeepResearchEval框架:标准化研究流程的动态编排引擎
  • WindowResizer完全指南:轻松突破Windows窗口尺寸限制的实用工具
  • Gemini-Nexus:高效集成谷歌Gemini大模型的Python开发工具
  • STM32U0系列MCU:超低功耗与安全特性解析
  • 基于树的有向图分析(CF2208D1D2)
  • BabylonJS 6.0相机输入进阶:用HammerJS实现媲美Google Earth的触摸手势控制
  • 告别Android 14系统分区挂载失败:深入理解vdc与checkpoint机制
  • Testsigma深度解析:AI驱动的智能测试自动化平台架构解密与实战指南
  • 盲点监测MCP服务器:为AI智能体开发提供实时质量护航
  • JPEXS Free Flash Decompiler:终极SWF反编译工具完全指南
  • 告别点灯Demo!用GUI-Guider给STM32F4做个触控开关(附源码)
  • Win10/Win11系统下PySide6安装避坑指南:从‘DLL加载失败’到成功运行第一个窗口
  • 如何快速解决ComfyUI ControlNet Aux中DWPose ONNX运行时错误:终极指南
  • 对比自行搭建代理,使用 Taotoken 在响应速度上的实际感受
  • 行为参数化
  • 为什么你的Minecraft整合包分享总是不顺利?5个技巧彻底解决
  • ctransformers:在CPU上高效运行大语言模型的Python推理引擎
  • 超越牛顿-拉夫逊:用MATPOWER玩转概率潮流与连续潮流(附案例9代码)
  • PMP报考费用可以退吗 - 众智商学院官方
  • Windows右键菜单终极管理指南:如何用ContextMenuManager彻底告别混乱的右键菜单
  • Simulink建模避坑指南:手把手教你用MAB规范检查工具,让模型一次达标
  • 【YOLOv11】077、YOLOv11边缘计算部署:边缘服务器与端侧协同推理
  • 低比特量化技术M2XFP:提升深度学习模型压缩效率
  • 如何轻松掌控笔记本电脑风扇:NBFC Linux 全面配置指南
  • 【开源库比较】感觉sweetAlert在语义上没artDialog好用
  • OneMore:5个核心模块重塑你的OneNote生产力工作流
  • 3步实现Word文档自动化转换:Mammoth.js终极实战指南
  • 视频字幕提取终极指南:3步实现本地化硬字幕转SRT
  • 告别Myo Connect依赖:手把手教你从蓝牙协议层直接读取双Myo臂环数据