스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
HealthKit Medications API 만나보기
HealthKit에서 새로운 Medications API를 확인하세요. 새로운 API를 사용하는 예제 앱을 살펴보고, 의약품 및 투여 정보에 액세스하는 방법을 학습하며, 앱이 이와 같은 새로운 유형의 데이터 승인을 관리하는 방법을 알아보세요.
챕터
- 0:00 - Introduction
- 2:12 - Medications API overview
- 5:35 - Examples of medication data
- 8:58 - Sample app walk-through
- 18:21 - Anchored object queries
- 22:39 - Authorization for new meds
리소스
- Authorizing access to health data
- HKAnchoredObjectQuery
- HKSampleQuery
- Logging symptoms associated with a medication
- requiresPerObjectAuthorization()
관련 비디오
WWDC25
WWDC20
-
비디오 검색…
Hello! My name is Eric and I am an iOS developer on the Health team.
Today, I’m going to introduce you to the new medications APIs added to HealthKit that can power exciting experiences on iOS, iPadOS, and visionOS. Hi! I am Srishti Gupta, I am also a software engineer in Health. Today I am going to show you an app I built that uses the new APIs that Eric will be introducing.
First, I’ll go over the new HealthKit API that allows your app to read medications data.
I’ll also give some examples of what this data looks like in Health.
Then, Srishti will walk you through a sample application that uses these APIs.
We’ll then go over anchored object queries, and how Health will help your app manage authorization of newly added medications. Before I get into the details of the new APIs, let me show you how medications data gets added to HealthKit.
In iOS 15, the Health App added medication tracking. You can find medication tracking in the Search tab in Health.
Tap on Medications to get started. You’ll be taken to the medications view; if you haven’t added any medications yet, you can add your first one by tapping “Add a Medication”.
When you’re adding a medication, you’ll first search for it. Many medications have the same name, but they can have different strengths and come in different forms.
Once you’ve selected a specific medication, you can also set up a reminders schedule to help keep you on track.
You’ll also be able to add some extra details about your medication to personalize it.
When you’re done, the medication will be added to your list! You can log your medications anytime. Each time you log, you can choose the amount you took and when. When the system presents a notification reminding you to log your medications, you can pick Taken, Skipped, or snooze the notification for 10 minutes.
Whether you’re adding medications, or logging dose events your data is securely stored in HealthKit.
Today, the data your apps can fetch from HealthKit is expanding. We’re adding the ability to read medications and dose events! The object that represents medications is named HKUserAnnotatedMedication.
HKMedicationDoseEvent represents the doses logged for a medication, its a new kind of HKSample. Your app uses query descriptors and HKQueries to fetch data from HealthKit, and we’re introducing a new query descriptor, and a new HKQuery to fetch medications. These are named HKUserAnnotatedMedicationQueryDescriptor and HKUserAnnotatedMedicationQuery.
First, I’m gonna hone in on the two objects that represent medications and dose events.
User annotated medications represent a specific medication and its customizations. They are made up of four properties. isArchived is a flag that indicates a medication is finished or no longer being taken. These medications are neatly tucked away in an archived section, and don’t show up in the active medications list.
hasSchedule tells your app if a medication has a reminders schedule set up. If it does, the system will regularly present notifications to log this medication. A nickname is a more memorable way of referring to a medication, rather than its longer clinical name. It’s used for personalization and making medication management less clinical and more friendly. Theres also a reference to the actual medication being taken.
A HKMedicationConcept embodies that specific medication.
We call this a medication concept, since it only represents the conceptual idea of a medication, not something like a prescription record. Its identifier is unique among all medication concepts, ensuring your app can reliably identify the same medication across different devices and over time.
Its display text represents a name for the medication.
It’s general form indicates the physical form of the medication like capsule, tablet or liquid. Different forms of medications may have different ways of administering them.
Finally, related codings contains a set of clinical codes associated with this medication. These codes can come from standardized terminologies like RxNorm.
This allows for interoperability with other health systems and a more robust way to identify and categorize medications. Dose events represent the times a medication was supposed to be taken, or actually taken. They are a new kind of HKSample. They are always related to a specific medication, by its medication concept identifier. They also contain the log status of the event, like taken or skipped. Scheduled doses can also be snoozed, or not interacted with entirely. Doses saved for these cases will have a log status that reflects them. Each dose event also captures how much of a medication was logged. Scheduled dose events will have the date, and amount for that scheduled dose. If the scheduled quantity differs from the dose quantity, that means there was a difference between what was scheduled to be taken, and what was actually taken.
To reiterate, dose events are tied to a medication. The medication concept identifier is the same as the identifier property of a medication concept. Your app will fetch HKUserAnnotatedMedications from HealthKit. When your app queries for them, they’ll represent the current state of the customizations in Health.
Now, let me walk you through a medication added to Health, and show you where you can see it’s details and customizations. Let’s say you’ve added Amoxicillin to Health. You’re about to take a course of antibiotics to fight off an infection. When your app queries for medications, it will get an object back that represents Amoxicillin and its customizable properties.
Theres no schedule set up for this medication at the moment, its “As Needed”. And the nickname you gave it is “Antibiotics” since that reflects why you’re taking it. Amoxicillin is represented by a medication concept. It has its own unique identifier, it’s name is “Amoxicillin Trihydrate 500mg Oral Tablet”, it’s manufactured as a tablet. and there’s a single related coding. An RxNorm code of 308192.
Your app can use this HKUserAnnotatedMedication to create an experience like the one shown in the Health App. It contains the customizable components, and the specific details about the medication.
Your app queried for the medications in Health, but to power experiences based off of how this medication was logged, your app will also want to fetch Dose Events.
Let me walk you through an example of a logged dose event, and show you what values your app can expect on these properties.
Its important to take antibiotics on a regular cadence, so you set up a schedule for it.
A reminder was sent to take Amoxicillin, but you skipped it. When you skipped that reminder, a dose event was saved to HealthKit. Your app will start a query for medication dose events, and get that sample back in the results handler. This dose event’s status is skipped. Since no medication was taken, it’s dose quantity is 0. The sample’s start date is the time picked when logging. This dose event is a record of a specific scheduled event. Scheduled date and scheduled quantity match the scheduled event. The date is the time the event was set for, and the quantity is the amount that should have been taken. There will be dose events saved for every scheduled dose of a medication.
Finally, this dose event is associated to the Amoxicillin medication concept, by its medication concept identifier.
Your app can use HKMedicationDoseEvents to create experiences based off of how someone logged their medication. They capture the context and details of what was logged.
Now that I’ve shown you the two objects your app can use to incorporate medications data, let me show you the queries your app can use to fetch them. To fetch the list of medications, your app should use the new query descriptor. Your app can use it to fetch the list of active and archived medications from HealthKit.
There are two new predicates you can use with this query descriptor. One for isArchived and one for hasSchedule. Your app can also specify a limit.
If the query descriptor is configured with a predicate, your app will only receive medications that match that predicate. In this case, your app wouldn’t see Piroxicam, since its archived.
Dose events are HKSamples, and your app can use any of the existing sample type based queries to fetch them, like sample queries, anchored object queries, and observer queries. When configuring these queries, your app should use the new HKMedicationDoseEvent sample type.
We’ve also introduced a variety of new query predicates for dose events. When considering which dose events to fetch, it’s most useful to fetch them by medication, or by log status.
Now that I’ve given you an overview of these APIs, and some examples of data, let’s check in with Srishti. She’s built an app that incorporates medication and dose event data from HealthKit. Srishti, I’m curious to know more about the app you built. I’d also love to see how you’re using the medications API! Would you mind giving us walk through? Of course, Eric! Let me walk you through the app I built. It’s for viewing dose events and logging side effects for a medication. I am going to show you it in action. You can also download the sample app for this session from the link provided in the session's description page.
When you open my app, you’ll see a list of medications that are already authorized. These are the medications that have been added to the Health App. When I tap on a specific medication, I get the most recent dose I have taken today. I logged it as taken this morning in the Health App. I can also see a list of side effects that I might be experiencing. These side effects are linked to this specific medication. Since I’m dealing with a nasty headache, I’ll select that symptom and mark it as severe by selecting an emoji. Then, I’ll tap on the ‘Save to HealthKit’ button to save the sample. Now that I’ve given you a quick rundown of my app, let’s dive into the details of how I put it together. First things first, we need to ask the user for permission to read and share their data.
My app uses the HealthKit per-object authorization API I to request read access for medications data since medications are objects not samples. This request is embedded in a Swift UI View. Then, I configured my request with a health store, and a new object type, HKUserAnnotatedMedicationType. I also used a state variable to indicate, when the authorization prompt should be triggered. When this state variable is changed to true, the system presents with a list of medications added to the Health app. Users can toggle the medications they wish to share with my app, then tap ‘Allow'.
After authorization is reviewed, the completion handler will be called, enabling me to handle any errors gracefully. I don’t need to request authorization separately to read medication doses. When someone authorizes a medication, my app is automatically granted access to read that medication and its doses. In a separate request, my app will also request, read, and share access to symptom samples, such as nausea and headache. I will use a similar API call for health data access request. But, the difference here is that I provide a list of sample types to read and share instead of a single object type. Changing the state variable to true initiates an authorization request, displaying a sheet for selecting data types requested for reading and sharing. Users can toggle the desired symptom types and then tap 'Allow.' The completion of this authorization request must be handled similarly, ensuring that my app fails gracefully if the authorization was not successful.
After determining the authorizations, my app will then query for the complete list of authorized medications from HealthKit.
To do this, my app uses an async function that returns an array of HKUserAnnotatedMedications. First, this function configures a query descriptor to fetch the authorized list of medications; These are the medications that someone has added to Health! For this query there is no predicate or limit needed, since we want to fetch both active and archived medications. Then, I’ll await the results from the query descriptor, using a reference to a Health store. The class that implements this function is responsible for multiple queries, so it maintains a reference to a health store as an instance variable. My app will only see medications for which someone has granted authorization. If I have results from the query then I will take the list of medications from this function, and use them to populate the main view of my app. Once someone taps on a medication, we’ll need to perform another query to fetch the dose events for the medication detail view.
This time we need to query for a medication dose event that was logged for today. Now, I’m going to show you how I set up my query descriptor for fetching the latest dose event.
For fetching the latest dose, I wrote a function that accepts a HKMedicationConcept, and returns a single optional HKMedicationDoseEvent. If no doses are logged for today, this dose event for that medication will be nil.
I set up a compound predicate, to bound my results since I care about dose events for the medication provided, doses that were logged today and have a status of taken. To see more details of how I configured this sample predicate, please take a look at the sample app.
Then I configured the rest of my sample query descriptor, and returned the first object of the awaited results. The sort descriptors and limit will ensure my results only have the most recently logged dose that matches my predicates.
After I’ve retrieved today’s dose I use it’s start date to set up my dose tile. If there’s no logged dose for today, I’ll show nothing.
My app has successfully fetched medications and dose events from HealthKit. I now want to display a list of relevant side effects associated with a specific medication. To accomplish this, I did some research about which medications have which side effects.
Any medication may have a list of side effects, and HealthKit has category types that reflect some of these symptoms like headache, nausea and many more.
When I did my research, I associated codes in a system called RxNorm with a symptom model that captures the symptom name, and the category type identifier. RxNorm encodes clinical drugs as unique identifiers that represent an individual concept. I encoded the associations I researched in a static structure in my app. I am going to show you how I related a medication to a list of side effect sample types through RxNorm codes.
First, let’s take a look at the diagram that Eric showed earlier, I used the related codings property on HKMedicationConcept. It contains a set of clinical codings that represent this medication.
A clinical coding is a code contextualized in a system. These codes represent specific medical concepts, like allergies, conditions, and in our case medications. Systems are identified according to the official FHIR Terminology.
The system I care about, RxNorm, has the following URL that uniquely identifies it. To learn more about how we model these codings, check out our developer documentation. Now, let me show you how I use the RxNorm system in my app.
I decided to enhance my side effect structure to match the known side effects to a specific medication. The first thing I did was add a constant for the RxNorm system.
Then, I introduced a function to retrieve symptom types for an HKMedicationConcept. This function matches a medication’s RxNorm codes to symptom models using the data from my static dictionary. I used the SideEffects static function to fetch all the associated symptoms for the medication and then displayed them in the medication detail view. Now that my app has a set of symptoms for a medication, I went ahead and implemented an experience to record symptoms. My personal favorite way to represent and log symptom intensity is using emojis.
To start with, I picked these 5 emojis that represent a symptom feeling from none to extreme.
Then, I created a new enum called SymptomIntensity. I want to turn this intensity into a category sample to save to HealthKit, so I associated its cases to a corresponding category value.
To tie it all together, I wrote a function that creates a sample for a category type and a SymptomIntensity. I’ll save the sample using the existing save method on the Health store.
Now, when I tap on a symptom type, I get an emoji picker. I can choose an emoji to represent the intensity of my symptom and save it to HealthKit, just like that.
Thats my app so far! I went over all the different experiences I have built, and the different medication queries my app uses to fetch the data. Also I showed how I utilized the RxNorm system to associate symptoms and display them in my app.
I’m also thinking about adding a new charts experience, where I can track my medication doses logged over time.
Eric, I was thinking about using an anchored object query to observe and fetch the underlying data and then populate my charts. What do you think? Thanks so much for that awesome overview! I think an anchored object query would be a perfect fit for your charts experience.
Your chart can seamlessly update when there’s new doses saved to HealthKit.
Its important to be careful when using an anchored object querry for dose event data. Dose events may be logged for days in the past, deleted and re-persisted when editing, or may be saved for reminders that were never interacted with.
If handled incorrectly, it might look like inconsistent data.
Here’s a refresher on Anchored Object Queries, and some best practices to keep in mind.
When your app executes an anchored object query, your app will receive a snapshot of existing samples. When there’s an update, your app receives an additional set of results, which may contain deletes for samples your app already processed.
Anchored object queries can be used in all sorts of ways. They’re an efficient way to make sure your app is getting new data added to HealthKit.
Remember, anchored object queries are useful for fetching data with respect to the query anchor provided. If you already fetched data from an anchored object query, use the returned query anchor to make sure your app does not process the same data again. If your app wants to start a query from the beginning, provide nil for your query anchor.
Your app should reflect the newest dose event data added to HealthKit. Dose events capture interactive logging behavior, so it might be jarring for someone to see stale data in your app. Make sure you’re using anchored queries to continuously keep your apps data up to date, so it matches what’s shown in Health.
Using anchored object queries is in general more efficient than setting up a paired observer query and a sample query.
Lastly, there is a swift async interface for anchored object queries! This interface delivers a stream of results, usable with swift async / await.
If you haven’t used an anchored object query before, or are curious for more information and examples, see our developer documentation. And watch our Getting started with HealthKit WWDC Talk! Lets see how Srishti is going to use an anchored object query to fetch data for her charts. Srishti, can you show us how you’re implementing this query? I’d be happy to! I’m thinking about the query I am going to write; it should make sure we only fetch logged doses for a medication, and fall within the chart date window.
I’ll also need to keep track of how my app’s data is getting updated. To set up my anchored object query, I’ll start by configuring my query just like the sample query I created earlier. I’ll use the same predicate for fetching doses by medication and by log status, but I’ve replaced the predicate for today, with one that matches doses that fall within my chart date window.
To see more details of how I configured this predicate, please take a look at the sample app.
I’ll supply nil for the anchor since I want to start from the beginning of all logged dose events. I am using a swift async interface to execute the query on a background thread. Once I get the results from the query, I will process them in a separate function to update my app’s data model. I’ll do this in a new function called handleResult.
First I need to get the deleted objects from the result, and clean up any data that has been deleted. Then, I will need to update my set of chart points with the new samples added. To see more details of how I managed my chart points, please take a look at the sample app.
Now, let’s take a look at the UI and I’ll show you how my charts update when new data is saved. Here’s my chart, where the X-axis represents individual days, and the Y-axis represents the number of doses taken for a medication. You can pick different medications in the horizontal scroll view.
On my watch I am going to mark my dose in the Medications app.
Since, I’m using an anchored object query to constantly check for new data, my chart automatically updates with the new data I logged in on my watch. I’m super thrilled with how my charts turned out! It will display the most recent data saved to HealthKit, which is incredibly convenient to keep an eye on doses logged over time.
But Eric, what happens when I add a new medication to the Health App? Thats a great question.
Everything we’ve shown you so far has assumed that your app has authorization determined for all the medications added to Health.
Let’s say, your app has been installed and authorized successfully for medications data.
Someone using your app now wants to add a new medication to their active list.
They want their new medication to appear alongside their other active medications, so they’ll come back to the Health App to add it. They’ll search for the new med they want to add, and customize it. Before adding it to their list, there’s a final step.
Since your app has already requested access to medications, Health App will present your user with a switch where they can select your app to share with! This is just like asking for authorization, except from within the Health App, and does not require any additional work from your application.
Once they select your app, they’ll save their medication to Health.
When they go back to your app, they can see the newly added medication. Managing authorization in this way makes it seamless and easy for your app, and your users. So that’s the medications API! From unique personalizations, to doses over time — your app has everything it needs to create a great experience with medications data. It’s all connected through a specific medication concept, which you can relate to other clinical data. Just think of all the experiences that can help people understand how the medications they are taking impact their Health.
I hope you can find interesting ways of incorporating medications in your app.
Before we say goodbye, here’s a few things you should know. We just scratched the surface while going over the sample app, and theres so many directions you can take with it. Download the sample app, and look at the example code to help kickstart development of your own applications.
To get even more out of the HKMedicationConcept API, dive into clinical coding systems like RxNorm to help categorize and identify medications, and associate them with insightful data, like side effects or education content.
Take a look at our developer documentation to learn more about what different log statuses mean, for more query predicates, and for other capabilities of HKMedicationDoseEvent.
And lastly, check out our other developer talk, “Meet workouts on iOS.” Thanks for exploring the medications API with us today! We are looking forward to see what you create. And please let us know what you think of these new APIs using feedback assistant! Thanks for watching!
-
-
- 0:00 - Introduction
HealthKit has introduced new medications APIs enabling iOS, iPadOS, and visionOS apps to read and utilize medication data. The Health App in iOS 15 allows users to track medications, set reminders, and log doses securely within HealthKit. Developers can now leverage these APIs to create personalized health experiences.
- 2:12 - Medications API overview
HealthKit's data capabilities are now expanded to include medications and dose events. Apps can access this information through new objects and queries. You can use new query descriptors and 'HKQueries' to fetch these medications and dose events, enabling apps to provide more comprehensive medication management and interoperability with other health systems.
- 5:35 - Examples of medication data
In the Health app, when someone adds a medication, like amoxicillin, it's represented as an object with customizable properties. This object includes the medication's official name, form (like tablet), unique identifier, and an RxNorm code. The person can also set up a schedule and give it a nickname, such as "Antibiotics," for easy reference. Apps can use specific queries to fetch this data. To retrieve a list of medications, apps can use a new query descriptor that allows filtering by active or archived status and schedule presence. To fetch dose events, apps can use existing sample type-based queries, specifying the 'HKMedicationDoseEvent' sample type, and filtering by medication or log status.
- 8:58 - Sample app walk-through
The sample app utilizes HealthKit's medications API to enable users to view their authorized medications, log the most recent dose taken, and record side effects. The app requests user permission to read and share medication data and symptom samples such as headaches and nausea. Upon authorization, the app queries HealthKit to fetch the complete list of authorized medications and their corresponding dose events. The app retrieves the most recent dose of a specific medication logged today using a HealthKit query with a compound predicate. If it doesn't find a dose, nothing is displayed. The app then associates medications with side effects using RxNorm codes, a system that uniquely identifies clinical drugs. A static dictionary in the app maps RxNorm codes to symptom models. People can view a list of associated side effects for a medication and log their symptom intensity using emojis, which are then saved as category samples in HealthKit.
- 18:21 - Anchored object queries
One consideration is to add a feature to the app to track medication doses over time using anchored object queries. An anchored object query is an ideal solution for updating charts with new dose data from HealthKit. This query method provides a snapshot of existing samples and subsequent updates, including deletions. However, careful handling is essential due to the dynamic nature of dose event data, which you can log retroactively, edit, or save for reminders. When implementing an anchored object query, it's crucial to use the returned query anchor to avoid reprocessing data. Configure the query with a predicate that filters doses by medication and falls within the relevant date window. The Swift async interface is recommended for efficient execution on a background thread. This real-time data synchronization provides people with a convenient way to monitor their medication intake over time.
- 22:39 - Authorization for new meds
When a person adds a new medication to their Health app, they're prompted to choose which apps, already authorized for medications data, can access the new medication. This seamless process occurs within the Health app and doesn't require any additional development work. After the user selects the app, the medication is saved, and the app can then display the newly added medication. The medications API enables apps to create comprehensive medication management experiences, utilizing clinical coding systems like RxNorm for enhanced categorization and data association.