
-
了解 HealthKit Medications API
了解 HealthKit 中的全新 Medications API。探索一个使用此全新 API 的示例 App,了解如何访问药品和剂量,并了解你的 App 如何管理此类新数据的授权。
章节
资源
- Authorizing access to health data
- HKAnchoredObjectQuery
- HKSampleQuery
- Logging symptoms associated with a medication
- requiresPerObjectAuthorization()
相关视频
WWDC25
WWDC20
-
搜索此视频…
大家好!我叫 Eric 是健康团队的 iOS 开发者 今天我将为大家介绍 HealthKit 增加的 新 medications API 它们能在 iOS、iPadOS 和 visionOS 上实现优秀的体验 大家好!我叫 Srishti Gupta 我也 来自健康团队 是一名软件工程师 今天 我将向大家展示 我开发的一款 App 这个 App 就使用了 Eric 要介绍的新 API
首先 我要介绍一下新的 HealthKit API 它能帮助你的 App 读取用药数据 我还会举一些例子 说明这些数据在 “健康”App 中的应用 然后 Srishti 将介绍 使用这些 API 的 App 示例
接着 我们将介绍锚定对象查询 以及“健康”App 将 如何协助你的 App 管理对新添加药品的授权 在详细介绍新 API 之前 我来演示一下如何将用药数据 添加到 HealthKit 中
在 iOS 15 中 “健康”App 添加了用药跟踪功能 你可以在“健康”App 的 “搜索”标签页中找到用药跟踪信息 轻点“用药” 我们将进入“用药”视图 如果还没有添加任何药品 可以轻点“添加用药” 添加第一个药品 添加药品时 我们需要先搜索一下 许多药品名称相同 但效力却不同 并且有不同的形式 选定一款药品后 我们还可以设置定时 以便提醒我们按时用药 我们还可以根据自己的情况 添加一些具体的药品信息 完成后 用药情况 将添加到你的列表中
你可以随时记录用药情况 每次记录时 你可以选择用药剂量和时间 当系统显示通知 提醒你记录用药情况时 你可以选择“已用药”、“已跳过” 或者将通知推迟 10 分钟 无论是添加药品 还是记录剂量事件 数据都会安全地存储在 HealthKit 中 现在你的 App 可以 从 HealthKit 中获取更多数据 我们将增加读取药品 和剂量事件的功能! 表示药品的对象名为 HKUserAnnotatedMedication HKMedicationDoseEvent 表示记录的药物剂量信息 这是一种新 HKSample App 使用查询描述符 和 HKQueries 从 HealthKit 获取数据 我们还推出了一种新的查询描述符 以及一个新的 HKQuery 来获取药品数据 这些描述符分别被命名为 HKUserAnnotatedMedicationQueryDescriptor 和 HKUserAnnotatedMedicationQuery 首先 我将深入介绍这两个对象 它们分别代表药品和剂量事件 用户备注的药品代表 特定药品和一些自定信息 它们有 4 个属性 isArchived 是一个标志 表示用户已经结束用药 或不需要再用药 这些药品折叠在“存档”部分 不会出现在活跃的药品列表中 hasSchedule 会告知 App 某种药物是否设置了定时提醒 如果已经设置定时提醒 系统将定时显示通知 以记录用药情况 nickname 表示药品的别名 比长长的临床名称更容易记住 用户可以自己设定药品的别名 方便用户轻松管理用药 其中还会记录药品 实际的临床名称 HKMedicationConcept 能够表示具体的药品 我们称之为药品概念 因为它只代表了药品的概念 而并不是处方记录 药品的 identifier 在所有药品概念中是唯一的 能确保 App 能够准确地 在不同的设备上和 不同的时间识别同一种药品 displayText 代表药品的名称 generalForm 表示 药品的物理形态 如胶囊、片剂或液体 不同形式的药品 可能有不同的给药方式 最后一个是 relatedCodings 包含一组与药品关联的临床代码 这些代码可以来自标准术语 例如 RxNorm 中的术语 这有助于与其他健康系统实现互操作 而且也能更可靠地 识别药品和进行分类 剂量事件代表计划的用药时间 或实际用药时间 这是一种新的 HKSample 通过 medicationConceptIdentifier 与特定的药品关联 还包含事件的 logStatus 比如“已用药”或“已跳过” 用户可以推迟定时用药 或者不进行任何操作 这些情况下保存的用药情况 有一个能反映用药情况的 logStatus 每个剂量事件还会捕获 所记录的用药剂量 添加了定时的剂量事件将包含 设定的用药日期和剂量 如果 scheduledQuantity 与 doseQuantity 的值不同 则表示设定的用药剂量 与实际用药剂量之间存在差别 重申一下 剂量事件会与药品关联 medicationConceptIdentifier 与 药品概念的 identifier 属性相同 App 将从 HealthKit 获取 HKUserAnnotatedMedications 当 App 查询这些标识符时 它们将表示“健康”App 中 自定项的当前状态 现在我演示一下 在“健康”App 中添加药品 并介绍可以从哪里查看 详细信息和自定项 假设我已经在“健康”App 中 添加了阿莫西林 我要服用一个疗程 的抗生素来抵抗感染 当 App 查询药品时 App 会收到一个表示阿莫西林 和它可自定属性的对象 这个药品目前没有设置用药定时 它的状态是“按需” 我给它标记的别名是“抗生素” 因为这个名字能反映用药的原因 阿莫西林用药品概念表示 它有自己的唯一标识符 名称是“Amoxicillin Trihydrate 500mg Oral Tablet“ 它的形式为片剂 并且有一个关联的代码 RxNorm 编码是 308192 App 可以使用这个 HKUserAnnotatedMedication 打造类似“健康”App 的体验 它包含可自定的组件 以及有关药品的详细信息 App 在“健康”App 中查询药品 但为了提升记录用药的用户体验 App 还需要获取剂量事件 我来演示一个 记录剂量事件的例子 并展示 App 可以预计 这些属性能提供哪些值 抗生素需要按时服用 所以要设置一个定时用药提醒 我看到了服用阿莫西林的提醒 但我跳过了 当我跳过这个提醒时 会有一个剂量事件保存到 HealthKit App 将开始查询用药剂量事件 并在结果处理程序中收到样本 这个剂量事件的状态是“已跳过” 由于没有用药 因此剂量为 0 示例的开始日期是 记录时选择的时间 这个剂量事件是特定设定事件的记录 设定日期和设定数量 与设定的事件一致 日期与为事件设置的时间一致 剂量与设定的用药剂量一致 App 会为设定的每次用药 保存剂量事件 最后 这个剂量事件与 阿莫西林药品概念 通过 medicationConceptIdentifier 进行关联 App 可以使用 HKMedicationDoseEvents 围绕用户记录用药的方式 打造用户体验 它们能捕捉记录内容的背景和细节 刚刚我展示的是 App 可以用来整合药品数据 的两个对象 接着我要展示 App 可用于获取这两个对象的查询 要获取药品列表 App 应使用新的查询描述符 App 可以用它从 HealthKit 获取 活跃的药品和存档的药品 有两个新的谓词 可与这个查询描述符一起使用 一个是 isArchived 另一个是 hasSchedule App 还可以指定限制 如果为查询描述符配置了谓词 App 将只接收 与这个谓词匹配的药品 这种情况下 App 中不会显示吡罗昔康 因为它已经存档 剂量事件是 HKSamples App 可以使用 任何基于现有示例类型的查询 来获取它们 例如示例查询、锚定对象查询 以及观察者查询 配置这些查询时 App 应使用新的 HKMedicationDoseEvent 示例类型 我们还为剂量事件引入了 多个新的查询谓词 要获取剂量事件 最实用的方式就是 按药品或记录的状态获取
我刚刚概括介绍了这些 API 和一些数据示例 接下来交给 Srishti 她开发了一款 App 能整合 来自 HealthKit 的药品 和剂量事件数据 Srishti 给我们详细介绍一下 你开发的 App 吧 我还想看看你是怎么 使用 medications API 的! 可以给我们介绍一下吗? 没问题 Eric! 我来介绍一下我开发的 App 这款 App 用于查看剂量事件和 记录药品的副作用 我来演示一下怎么用 大家也可以使用 讲座描述页面中提供的链接 下载这次讲座中提到的示例 App 打开这款 App 时 我们会看到一个药品列表 这些药品已经获得授权 这些是已添加到 “健康”App 中的药品 当我轻点其中的一个药品时 我可以看到今天 最近一次用药的时间 我今天早上在“健康”App 中 记录为“已用药” 我还可以看到 可能出现的副作用列表 这些副作用与这种特定药品有关 由于我最近会感觉到头疼 我将选择这个症状 并选择了一个表情符号 表示副作用严重 然后 我轻点“Save to HealthKit” 按钮保存这个示例 我开发的这款 App 基本就是这样 接着 我们来深入了解一下我如何 将它与“健康”App 关联在一起的 首先 我们需要请求用户授予 读取和共享数据的权限 我的 App 使用 HealthKit 按对象授权 API 来请求读取药品数据的权限 因为药品是对象不是示例 这个请求嵌入 在 Swift UI 视图中 然后 我使用 healthStore 和一个 新的对象类型 HKUserAnnotatedMedicationType 配置了我的请求 我还使用了一个状态变量来表示 何时应触发授权提示 当这个状态变量更改为 true 时 系统会显示添加到“健康”App 的药品列表 用户可以切换 愿意与我的 App 共享的药品 然后轻点“允许” 授权经过审核后 将调用完成处理程序 让我能够妥善处理任何错误 我无需单独申请授权 即可读取用药情况 当用户授权读取药品时 我的 App 会自动获得 读取药品和用药情况的权限 在单独的请求中 我的 App 还将请求、读取 和共享对症状示例的访问权限 例如恶心和头痛 为了请求访问“健康”数据 我将使用类似的 API 调用 但区别在于 我提供了一个 读取和共享的示例类型列表 而不是单个对象类型 将状态变量更改为 true 将发起授权请求 显示用于选择请求读取和共享的 数据类型的表 用户可以切换自己的症状类型 然后轻点“允许” 完成这个授权请求 必须以类似的方式处理 确保授权失败时 App 能妥善处理 确定授权后 我的 App 将查询从 HealthKit 已授权药品的完整列表 为此 我的 App 使用异步函数 返回一个 HKUserAnnotatedMedications 数组 首先这个函数 会配置一个查询描述符 用来获取已授权药品的列表 这些是用户添加到“健康”中的药品 ! 这个查询不需要谓词或限制 因为我们要同时获取 活跃的药品和存档的药品 然后我将使用对 healthStore 的引用 等待查询描述符返回的结果 实现这个函数的类负责多个查询 因此会将对 healthStore 的引用 当做实例变量来维护 我的 App 只能显示 用户已经授权的药品 如果我从查询中得到了结果 接着我会获取这个函数提供的 药品列表 并用它们来 填充我 App 的主视图 如果用户轻点了一个药品 我们就需要执行另一个查询 为药品详细信息视图获取剂量事件 这一次我们需要查询 今天记录的用药剂量事件 现在 我将展示 如何设置查询描述符 用于获取最近的剂量事件 为了获取最近的剂量事件 我编写了一个函数 用来接收 HKMedicationConcept 并返回一个可选的 HKMedicationDoseEvent 如果当天没有记录剂量事件 这个药品的剂量事件将为 nil 我设置了一个复合谓词 来限定我的结果 因为我真正需要的是药品的剂量事件 当天记录的用药情况 和状态为“已用药”的事件 如果要详细了解 我是怎么配置这个示例谓词的 可以看一下示例 App 接着我配置了 示例查询描述符的其余部分 并返回了等待的结果 的第一个对象 排序描述符和限制 能确保我的结果只包含最近记录 且与我的谓词匹配的剂量事件 在我检索到当天的剂量事件后 我使用它的开始日期 来设置我的“用药”拼贴块 如果今天没有记录剂量事件 这里什么也不会显示
我的 App 从 HealthKit 成功获取到了药品和剂量事件数据 我现在想要显示特定药品 相关副作用的列表 为此 我针对哪些药品有副作用 做了一些研究
任何药品都可能有一系列副作用 HealthKit 有一个类别类型 能代表一些副作用的症状 比如头痛、恶心等等 在研究的过程中 我关联了一个名为 RxNorm 的系统中的代码 使用的是能表示症状名称 和类别类型标识符的症状模型 RxNorm 采用能代表单个概念 的唯一标识符为临床药物编码 针对我研究得出的关联信息 我在我的 App 中 用静态结构进行了编码 我来演示一下我是如何 通过 RxNorm 代码 关联药物和副作用样本类型列表的 首先我们来看一下 Eric 在前面展示的示意图 我使用了 HKMedicationConcept 上的 relatedCodings 属性 它包含一组代表 这种药品的临床编码 临床编码是系统中情境化的代码 这些代码代表特定的医学概念 比如过敏、疾病 在这里代表药品 系统根据官方 FHIR 术语进行标识 我使用的系统是 RxNorm 它的唯一 URL 如需 要进一步了解我们 如何模拟这些编码 请查看我们的开发者文档 现在 我来展示一下我是如何 在 App 中使用 RxNorm 系统的 我决定优化我的副作用结构 将已知副作用与特定药品进行匹配 首先我为 RxNorm 系统 添加了一个常量 然后 我引入了一个函数来检索 HKMedicationConcept 的症状类型 这个函数使用我静态字典中的数据 将药品的 RxNorm 代码 与症状模型进行匹配 我使用 SideEffects 静态函数来获取 药品的所有相关症状 然后在药品详细信息视图中显示 现在我的 App 有了 一组药品症状 接着我实现了一个记录症状的功能 我个人最喜欢使用表情符号 来表示和记录症状的严重程度 首先 我选择了这 5 个表情符号 代表无症状到症状严重 然后 我创建了一个名为 SymptomIntensity 的新枚举 我想将这个严重程度转换为类别示例 以保存到 HealthKit 中 所以我将它的用例 关联到相应的类别值 为了把它们关联在一起 我编写了一个函数 用来为类别类型 和 SymptomIntensity 创建示例 我将使用 healthStore 中 现有的 save 方法来保存示例 现在 当我轻点症状类型时 就可以看到一个表情符号选择器 我可以选择一个表情符号 来表示症状的严重程度 并保存到 HealthKit 中 就像这样 这就是我开发的 App! 我刚刚介绍了我构建的不同体验 以及我的 App 用于 获取数据的不同药品查询 我还展示了 如何使用 RxNorm 系统 来关联症状 并在我的 App 中显示 我还在考虑添加新的图表体验 以便随着时间 跟踪我的用药剂量 Eric 我正在考虑使用 锚定对象查询来 观察和获取底层数据 然后填充我的图表 你觉得怎么样? 非常感谢你的精彩介绍! 我认为锚定对象查询 非常适合你的图表体验 当有新的剂量事件保存到 HealthKit 时你的图表可以即时更新
为剂量事件数据使用锚定对象查询时 务必要小心 剂量事件可以在几天后记录 也可以在编辑时删除并 设置为持续事件 或者可以保存为从未交互过的提醒 如果处理不当 数据看起来可能不一致 我们来回顾一下 锚定对象查询 和一些需要记住的最佳做法 当 App 执行锚定对象查询时 App 将收到现有示例的快照 当有更新时 你的 App 会收到一组额外的结果 其中可能包含 删除 App 已处理的示例 锚定对象查询 有很多种使用方式 这是一种有效的方式 能确保 App 正在获取 添加到 HealthKit 的新数据 请记住 锚定对象查询 能够很好地用于获取 相对于提供的查询锚点的数据 如果你已经 从锚定对象查询中获取了数据 可以使用返回的查询锚点 来确保 App 不会再处理同样的数据 如果 App 希望从头开始查询 可以将查询锚点设置为 nil 你的 App 应反映添加到 HealthKit 的最新剂量事件数据 剂量事件会采集交互式记录行为 因此 在 App 中看到过时的数据 可能会让人感到不安 请确保使用锚定查询来持续 保持 App 数据是最新的以确保 与“健康”App 中显示的数据一致 使用锚定对象查询 通常比设置成对的 观察者查询和示例查询 更加有效 最后 还有一个 用于锚定对象查询的 Swift 异步接口! 这个接口会提供一系列结果 可与 Swift Async/Await 一起使用 如果你以前没有 使用过锚定对象查询 或者想了解更多信息和示例 请查看我们的开发者文档 并观看我们的 WWDC 讲座 “开始使用 HealthKit”!
我们看看 Srishti 将如何使用 锚定对象查询来为图表获取数据 Srishti 能给我们说说 你是怎么实现这个查询的吗?
没问题! 在设想要实现的查询时 我认为它获取的剂量事件应该 只针对某款药品 并且要在图表日期窗口内 我还需要跟踪 App 数据是怎样更新的 为了设置我的锚定对象查询 首先我会配置查询 就像我之前创建的示例查询一样 我将使用相同的谓词 按药品和记录状态来获取剂量事件 但我为今天替换了谓词 用的是在我的图表日期窗口内 且与剂量事件匹配的谓词 如需详细了解 我是如何配置这个示例谓词的 可以看一下示例 App 我将锚点设置为 nil 因为我想从所有记录的 剂量事件的开头开始 我使用 Swift 异步接口 在后台线程上执行查询 获得查询结果后 我会使用单独的函数处理它们 以更新 App 的数据模型 我会在名为 handleResult 的 新函数中完成这项操作 首先 我需要从结果中 获取已删除的对象 并清理已删除的数据 接着 我需要使用添加的新示例 更新我的图表点集 要查看有关如何 管理图表点的更多详细信息 可以看一下示例 App 接下来 我们看看用户界面 我来演示一下保存新数据时 图表会怎样更新 这是我的图表 其中 X 轴表示日期 Y 轴表示 药品的用药次数 我可以在水平滚动视图中 选择不同的药品 在 Watch 上 我将在“用药”App 中标记我的剂次 由于我使用锚定对象查询 持续检查是否有新数据 所以我的图表会根据我在 Watch 上 记录的新数据自动更新 我对我的图表效果充满期待 它将显示保存到 HealthKit 的最新数据 这样 我就可以很方便地 查看已记录的剂量 Eric 那当我在“健康”App 中 添加新药品时 会发生什么情况? 这是个好问题 到目前为止 我演示的所有内容 都假定 App 已获得授权 可以访问添加到“健康”App 中的所有药品
假设你安装了 App 并成功获得了 访问所有用药数据的授权 现在 使用 App 的用户想要 在活跃的用药清单中添加一款新药 他们希望新药品与 其他活跃药品一起显示 因此 他们会回到 “健康”App 进行添加 他们将搜索想要添加的新药品 并对它进行自定 在将新药品添加到列表中之前 还有最后一个步骤需要完成 由于你的 App 已经 请求访问用药请求的权限 用户会在“健康”App 中 看到一个开关 用户可以在这里选择 与你的 App 分享权限 这就像请求授权一样 只不过请求是在“健康”App 中完成的 并且不需要在你的 App 中 进行任何额外的操作 选择你的 App 后 用户会将 用药数据保存到“健康”App 中 他们返回你的 App 时 可以看到新添加的药品 以这种方式管理授权既方便你的 App 也方便用户 以上就是关于 medications API 的介绍! 从唯一的个性化设置 到记录的剂量 你的 App 拥有足够的权限 可以凭借用药数据打造出色的体验 这一切都通过 一个特定的药品概念联系在一起 你可以将它与其他临床数据相关联 想一想有哪些好的做法 可以帮助人们了解 他们正在使用的药品 对健康的影响 希望大家能找到有趣的方法 将用药数据整合到你的 App 中
结束今天的讲座前 我来总结一下 我们初步介绍了示例 App 也有很多大家可以借鉴的地方 欢迎大家下载示例 App 并查看示例代码 以便快速上手开发你自己的 App 如果希望充分利用 HKMedicationConcept API 可以深入了解 RxNorm 等 临床编码系统 以便对药品进行分类和识别 并将它们与副作用或教育内容 等重要数据联系起来 请查看我们的开发者文档 详细了解日志状态的含义 了解更多查询谓词以及 HKMedicationDoseEvent 的其他功能 最后 请观看 我们的其他开发者讲座 “了解 iOS 上的体能训练” 感谢大家观看 关于 medications API 的讲座! 期待看到大家开发的 App 欢迎大家使用“反馈助理” 分享自己对这些新 API 的看法! 感谢观看!
-
-
- 0:00 - 简介
HealthKit 推出了新的 Medications API,使 iOS、iPadOS 和 visionOS App 能够读取和利用用药数据。iOS 15 中的“健康”App 让用户能够在 HealthKit 中安全地跟踪用药情况、设置提醒事项和记录剂量。开发者现在可以利用这些 API 打造个性化的健康体验。
- 2:12 - Medications API 概览
HealthKit 的数据功能现已扩展,可涵盖用药和剂量事件。App 可以通过新对象和查询访问这些信息。 你可以使用新的查询描述符和“HKQueries”来获取这些用药和剂量事件,使 App 能够提供更全面的用药管理,并实现与其他健康系统的互操作性。
- 5:35 - 药品数据示例
在“健康”App 中,当用户添加阿莫西林等药物时,它会显示为一个具有可自定属性的对象。该对象包含药物的官方名称、剂型 (如片剂)、唯一标识符以及 RxNorm 代码。用户还可以设置时间表并给药物起一个昵称,例如“抗生素”,方便查看。 App 可以使用特定查询来获取这些数据。还可通过新的查询描述符来检索药物列表,并可根据药物的激活状态、归档状态及是否存在用药计划进行筛选。要获取剂量事件,App 可以使用基于现有示例类型的查询,指定“HKMedicationDoseEvent”示例类型,并按药物或日志状态进行筛选。
- 8:58 - 示例 App 演示
示例 App 利用 HealthKit 的 Medications API,让用户能够查看其授权的药物、记录最近服用的剂量并登记不良反应。该 App 会请求用户授权读取和共享药物数据和症状示例,例如头痛和恶心。 获得授权后,App 会查询 HealthKit,以获取完整的授权药物清单及其相应的服药记录。 这款 App 会使用包含复合谓词的 HealthKit 查询来检索当前记录的特定药物的最新剂量。如果找不到剂量,则不会显示任何内容。 随后,App 会通过 RxNorm 代码将药物与副作用关联起来。RxNorm 是唯一标识临床药物的系统。App 中的静态字典会将 RxNorm 代码映射到症状模型上。 用户可以查看药物的相关副作用列表,并使用表情符号记录症状的严重程度,系统随后将这些数据作为类别示例存储于 HealthKit 中。
- 18:21 - 锚定对象查询
可以考虑为 App 添加一项功能,通过锚定对象查询来跟踪一段时间内的用药情况。锚定对象查询非常适合用于从 HealthKit 中获取新的用药数据并实时更新图表。这种查询方法不仅能提供当前已有样本的快照,还能持续接收后续的更新,包括删除操作。但是,由于剂量事件数据具有动态特性,必须小心处理,你可以追溯记录、编辑或保存这些数据以便进行提醒。 在实现锚定对象查询时,务必使用返回的查询锚点,以避免重复处理数据。配置查询时,应使用谓词按药物进行筛选,并限定在相关的日期范围内。 建议使用 Swift 异步接口,以便在后台线程上高效执行。这种实时数据同步机制为用户提供了一种便捷的方式,帮助他们持续监测自己的用药情况。
- 22:39 - 新药品的访问授权
当用户向“健康”App 添加新药物时,系统会提示其选择已被授权访问药物数据的 App,以便这些 App 访问新添加的药物信息。整个流程在“健康”App 中一气呵成,无需任何额外的开发工作。 用户选择 App 后,系统会存储相应药物信息,然后 App 就会显示新添加的药物。Medications API 使 App 能够利用 RxNorm 等临床编码系统来增强分类和数据关联,从而创建全面的药物管理体验。