HealthKit offers more than ever to developers joining in Apple's vibrant health and fitness ecosystem. Discover new ways to integrate the popular activity-tracking features of Apple Watch with your own app. Learn how to contribute to an even more complete picture of users' health data by reading and writing Health Documents from your organization. Review core concepts for working with HealthKit and explore best practices for managing data to ensure your users enjoy a seamless experience.
[ Music ]
Good morning, and welcome
to Getting the Most Out of HealthKit.
I'm Matt, I'm a software engineer on the HealthKit team,
and I'll be joined on stage shortly by my colleague Jeff.
In this session, we'll be going over some great new
and recent additions to the HealthKit APIs
in iOS 10 and watchOS 3.
Just as importantly, we'll be covering some key features,
core concepts, and important workflows to make sure
that you're really able to get the most out of HealthKit.
We expect you have some familiarity with HealthKit
if you're here watching this session, but if you don't,
we'll list some past sessions at the end of this talk
that you can refer to later to get up to speed.
But for now, let's get started.
As all of you here know, Apple's health
and fitness ecosystem has become a huge hit with our users.
People are getting more fit and more healthy
because of the integration of HealthKit and now ResearchKit
and CareKit with your apps and devices
for iPhone and Apple Watch.
We want to make sure that you're able
to keep creating these great health
and fitness user experiences
that our users have come to expect and enjoy.
So today we're going to be covering all the things you need
to do to get these great experiences right.
First, we'll cover authorization,
which underpins everything else you do with HealthKit.
Next, we'll cover the Activity Rings API introduced in iOS 9.3
and Health Records introduced this year in iOS 10,
both of which happen to have important implications related
Finally, we'll spend the rest of the session going
over a wide range of best practices for handling data
when you're interacting with HealthKit.
So let's dive in.
First up is authorization.
If you've been using HealthKit for a while, some or even most
of this section might feel like review,
but we really recommend you pay important attention
to the details because they'll be important
for the stuff we cover later in this session.
We'll sprinkle in some best practices as well,
so keep your ears peeled.
iOS gives users full control over their health data
and which apps can access which parts of that data.
Before interacting with HealthKit,
your app should request access
to the appropriate types via HK Health Store,
and then the Health Store
in turn will present the appropriate authorization UI
to the user if necessary.
Be aware that the user can change permissions for your app
at any time, so you should keep
that in mind while you're developing your app.
And just as importantly, read authorization
and write authorization are completely independent.
That last bit can actually be a little tricky, so let's look
at it in a little more detail.
Here's how read and write authorizations work.
If the user grants you both read and write permissions
to a given HealthKit type, then your app can query and save data
for that HealthKit type just like you'd expect.
If the user grants you only read permissions for a given type,
then your app can read but not write HealthKit data
for that type.
So far, so good.
Now, if the user grants you write permissions
for a given type, then your app can write data to HealthKit
for that type but not read it back
from HealthKit for that type.
Write permissions do not imply read permissions.
However, there's an important exception to that point.
If your app has write permissions
for a HealthKit type, then you can read back data
that your app has written, just not data from other sources.
Finally, if the user denies you both read and write permissions
for a given type, then you can neither query nor save data
for that type.
And there's an important implication
of that last point as well.
If the user denies you a previously granted write
permission for that app,
then that means your app can no longer read any data
from HealthKit for that type,
even data that your app previously wrote,
so keep that in mind.
So that was all technically review,
but there is one important change to authorizations
in general in iOS 10, and that has to do
with usage descriptions.
Apps linked on or after iOS 10 must include a description
for the user of why they're trying to access health data.
This reinforces our principle of user control over data.
These usage descriptions should be declared
on your app's info.plist file as values
for the NSHealthShareUsageDescription
key if you're reading data
or the NSHealthUpdateUsageDescription
key if you're writing data.
As a refresher, this is how you request authorization.
The first thing we want to do is make sure
that HealthKit is even available on the current device.
For instance, maybe this instance
of our app is running on an iPad.
After we've established that, we list the types
that we're interested in reading and writing.
And finally, we call request authorization
on HK Health Store, pass in the types we're interested in,
and then handle the response and the callback.
What if you have a watchOS app?
Authorizations are shared between your iOS app
and its companion watchOS app,
and you can request authorization at any time
from your iOS code or your watchOS code.
However, the system authorization UI can only be
presented to the user on the phone,
so this has some important usability implications.
For instance, if the user is about to start a workout,
they might already have their phone wrapped up in an armband,
and if that's the case,
they can't really easily approve an authorization request
from your app, so this may not be the best time
to request initial authorization.
But there's an even more important case.
If the user's using a Watch app, their phone may not be nearby
at all, and if that's the case,
the authorization sheet can't even be shown.
So we really recommend you consider these important cases
when you're developing your Watch app.
Also remember that the response time
for the request authorization call is not guaranteed,
so definitely don't block any UI while you're waiting
for a response.
So clearly it's important
to get the authorization user experience right,
and on top of that, your app may be requesting access to some
or even many HealthKit data types,
so that all raises a really important question.
When should I be requesting access to some
or all of these types?
Here are our recommendations on that front.
First, we recommend that you request access
to sensible groupings of types that correspond
to logical activities in your application.
So for instance, say your app allows users
to track both food intake as well
as body measurements like BMI.
If that's the case, you might consider requesting access
to nutrition types the first time the user tries to log food,
but then requesting access
to body measurement types whenever the user tries
to log one of those.
One exception to that rule is
if your app has an on-boarding flow.
If this is the case, it might actually make sense
to request access to all the types your app wants
to use upfront because you're already in a context
where you can clearly explain to the user what your app is going
to be doing with those types.
Regardless of which you choose, we definitely recommend
that you frequently test authorization
You can easily reset the initial authorization flow
by deleting your app off of the device or out
of the simulator before building and running again
so that HealthKit presents the user
with the initial authorization flow all over again.
When you're doing this, be sure to test cases
where authorization is either delayed
or completely denied by the user.
How does your app function in these cases?
What capabilities are left over?
Finally, if we could summarize authorization
in one sentence, it's this.
Consider the user experience.
Don't present obstacles at inopportune times,
and ensure that your flows make sense.
So we've spent a lot of time talking about authorization.
Now let's move onto some new features since last year
in HealthKit, starting with Activity Rings.
Apple's developed a great health
and fitness tracking experience for the Apple Watch.
Users love how easy it is to track key activity metrics
and improve their day, and now in iOS 10 and watchOS 3,
users can even share their Activity Rings
with each other and compete.
Now we're giving you a great way
to incorporate this Activity Ring experience right
into your app with the Activity Rings API in iOS 9.3.
To do this, we start with an HKActivitySummary object.
HKActivitySummary represents the sum of a user's activity
over the course of a given day.
That includes their move calories, exercise minutes,
and stand hours, and their goals for each.
HKActivitySummary is a distinct type for authorization.
It's not an HKObject, but rather a special read-only type
that you request authorization for distinctly
from its component types.
That last part's really important.
HKActivitySummary covers some of the same HealthKit information
as the HealthKit types; active energy, exercise minutes,
and stand hours, but only on a daily aggregated basis.
So for instance, if you want to do something more specific
like contribute to a user's Move ring by writing
to the active energy type or shown finer grain statistics
for activity over the course of a given day, in that case,
you'd want to request access
to the constituent types separately.
Now, because an ActivitySummary object represents activity
over the course of a given calendar day, which may
or may not correspond to a particular 24-hour period,
we specify the day corresponding
to an activity summary using a DateComponents object.
Let's see how that works in the following example.
So suppose we want to fetch the activity summary for today.
To do that, we use an HKActivitySummaryQuery.
First, we use our calendar
to create a DateComponents object corresponding
to today using the required components;
era, year, month, and day.
Next, we use those components to create a predicate object
that restricts our query
to activity summaries whose day corresponds to today.
And then finally, we create our query, pass in the predicate,
and then handle the, in this case, single activity summary
that should come back in the response.
So that's how you retrieve activity summary data,
but the really fun part is showing the rings themselves.
To do that, we use HKActivityRingView on iOS
or the analogous WKInterfaceActivityRing
They look like this, and just like you'd expect,
they perform this great animation
when you call setActivitySummary, animated.
Some tips for using HKActivityRingView
Firstly, just like in the health and activity apps on iOS
and watchOS, the rings look best on a black background,
so we recommend display them similarly in your apps.
Secondly, if your app has sharing
and communication features, you can use the writable properties
of HKActivitySummary to construct your own object,
supply it to HKActivityRingView or WKInterfaceActivityRing,
and thereby display another user's rings alongside the
current user's rings in your own app.
Finally, when you're using HKActivitySummaryQuery,
remember to use the required DateComponents; era, year,
month, and day in your HKActivitySummaryQuery.
Date map can be notoriously tricky,
so if you have any questions about using Calendar
or DateComponents, be sure to check out this great talk
from a prior conference.
So we've been talking a lot
about authorization and Activity Rings.
Let's put it into action with a quick demo.
Here on the right, we have an up and coming app
for a medical group called LoopHealth.
This app has some other features,
but its main page is a dashboard with some helpful information,
so for instance, your doctor's name, upcoming appointments,
and some healthy tips.
LoopHealth wants their patients to live healthier daily lives
as well, so they saw this as a great opportunity
to incorporate Apple's Activity Rings right
onto their dashboard.
As you can see here,
we've already dropped an HKActivityRingView
into the storyboard for our application,
but we haven't actually written the code
that hooks it up with data yet.
Let's see how easy it is to do that.
So over here in Xcode, we have DashboardViewController.
This is the view controller we were just looking
at in the LoopHealth app.
It's pretty empty so far,
but we do have some helpful things filled in.
You can see right here we have an IBOutlet set up connected
to the activityRingView that's already in our app.
Up here we import HealthKitUI.
This is the new framework
that you can find HKActivityRingView in on iOS.
And finally down here, LoopHealth sets
up its app-wide HKHealthStore in its app delegate,
so we've just set up a simple computed property to retrieve it
for convenience when we need it.
Okay, so if we want to show an activity summary in our app,
the first thing we need to do is request read access
And since we're reading health data, that means we need
to include a usage description,
so let's go to our info.plist file and add a new key.
The key we're interested
in is called NSHealthShare UsageDescription,
which is written here in plain English as Privacy Health Share.
Perfect. And I'll drop
in a quick usage description, and that's it.
We're all set.
Now I can go back to DashboardViewController
and then write the code that actually requests authorization.
Since we want to show the initial prompt to the user
and also update our rings whenever the user navigates
to the dashboard tab, the perfect place to do that is
in the viewDidAppear method.
So I'll drop that in here.
And after our requisite call to super,
notice that we call RequestAuthorization
on HKHealthStore, pass in the activity summary type,
and then in the response, we call updateActivitySummary,
which we'll write to actually fetch and update the data.
Let's go implement that now.
So here's our skeleton for updateActivitySummary,
and what we want to do here is create an
HKActivitySummaryQuery, request today's activity summary,
and then set that activity summary
on our HKActivityRingView once we get it back.
First, let's create a DateComponents object
corresponding to today.
Since DateComponents only makes sense in the context
of a particular calendar, we set the calendar object
that we use back on the components object.
Next, we can create our predicate using
that components object, and once we have the predicate,
we can create our query, pass in the predicate,
and then in the response, we grab the single summary
that should come back for today.
Now, once we have that summary,
all we have to do is dispatch back to the main queue
to update our UI and then call setActivitySummary,
animated on our Activity Ring view.
Now that we have our query, all we have left
to do is execute it, and that's it.
So let's build and run and see how this all looks.
So first thing you see is now that we're requesting access
to activity summary, Health is asking the user
to approve authorization.
Let's approve read access for our activity type,
and while we're down there, notice that at the bottom
of the screen, that usage description that we added
for reading health data is included and shown to the user.
It's important to note that in a real app,
we'd want to make sure this description is localized,
so we'd include that in our info.plist.strings file instead.
I'll approve authorization here, and just like that,
we see the Activity Rings animate beautifully into place.
So that's how easy it is
to incorporate Activity Rings right into your own app.
Be sure to check out the API.
Next, I'll turn it over to my colleague Jeff who's going
to tell you about an awesome new feature in iOS 10.
Good morning, everyone.
My name is Joefrey Kibuule.
I work alongside Matt as an iOS software engineer
on the Health team.
Today I have the proud privilege to introduce
to you a new feature of iOS 10, Health Records.
Health Records provides an easy and portable way
to carry the information most personal
to you right on your smartphone.
Today the current experience
when users visit a medical professional and ask
for their health records afterwards is this.
A stack of documents which may be cumbersome
to find a particular piece of information.
health organizations have been providing their patients this.
CDs of digitized information which may be unintuitive to use.
But now with Health Records in iOS,
we can help solve this problem.
Through the work that we've done in this release,
your apps can start to unlock new possibilities
in the exchange and interaction of Health Records.
In fact, in the U.S., adoption
of these APIs can help health organizations comply
with new regulations that require them
to give their patients more control
of their own health data.
So first, an overview.
Health Records in iOS is an umbrella term we use
to represent a variety
of different patient visits generated
by health institutions.
Today we're adding support specifically
for health documents.
Standard machine-readable XML
that represents specific patient visits.
These include patient visit summaries,
continuity of care visits,
and operative notes, just to name a few.
We support the international HL-7 CDA standard
for interoperability with a variety of different providers.
These documents are available
through patient healthcare portals online
and can be imported via Safari, Mail, and now all of your apps.
These documents are stored just
like all other HealthKit data safely
and securely encrypted on your iOS device.
Next, let's talk about permissions.
Since so much information is contained
within each health document,
we give the user additional controls compared
to other data types in HealthKit.
Access is granted on a per-document basis in addition
to the health document data type.
As shown on the right, we present the UI in order
to allow the user to both view
and select the document before granting your app access.
This UI will present it whenever you query for a document
and a new one is available.
If you query for documents and none are, nothing has changed,
we will not show this UI to the user
and your query will return immediately with results.
If you query for documents while your application is
in the background, we will never prompt the user UI
to grant access to new documents.
HealthKit ensures that the user is always aware
when they're granting access to documents
to your apps the first time it occurs.
Next, let's talk about how to create a document in HealthKit.
When saving a document into HealthKit,
you can save the raw XML
into the new HKCDADocumentSample type.
We validate on creation to ensure compliance
with the standard and will throw errors if this fails.
We automatically extract the title, patient, custodian,
and author names whenever the document is saved into HealthKit
in order to make querying for these fields faster
without needing to read the entire document.
Let's take a look at this example in code.
We're going to take the documentData
and transform it into a data object.
The origin of this XML will typically come
from a health organization server.
We're then going to create a new HKCDADocumentSample passing
in that data object, setting the appropriate dates,
and any additional metadata, just like any other HKSample.
And then we'll save the document to the healthStore.
Now your health document is saved into HealthKit ready
to be used in other apps or viewed directly
by the user in the Health App.
Now, let's talk about querying for documents in HealthKit.
Since HKCDADocumentSample is a subclass of HKSample,
existing query objects you may be already familiar
with continue to work just as you'd expect.
However, you need to use the new HKDocumentQuery
in order to fetch the raw XML.
Fetching the raw XML's expensive, and we only do
so when explicitly specified.
We provide predicate support in order to query
for the automatically extracted fields, and then lastly,
to remember that since HKDocumentSamples are immutable,
to previously samples are considered new samples.
Now, let's take a look at an example of how to query
for documents in HealthKit.
In this example, we're going to query
for all the documents a user has stored.
So first, we need to get the document type.
We're going to pass the CDA identifier
into the document type forIdentifier method
We're then going to create an HKDocumentQuery.
You have additional fields in order to filter
and order the documents received back
to you the order that you'd like.
And then we execute the query in order
to get the HKCDADocumentSamples back from HealthKit.
One thing I want to note in this particular example we set
includeDocumentData to false.
Only ever set it to true
if you need the full raw XML document data.
Now, let's talk about some best practices when dealing
with the health documents in HealthKit.
First, check for validation errors whenever creating
The errors will tell you why we weren't able
to transform your raw XML into a usable sample.
Next, you should verify by the Health App
that you imported were correctly saved
and automatically extracted fields are present.
This way, you can tell that queries based
on those automatically extracted fields return the correct sample
that you'd expect.
And lastly, request the raw XML data only when you need to.
Queries that don't request, including document data,
will return the automatically extracted fields,
and this may be all you need for you and your users
to uniquely identify a document in HealthKit.
For more information on the HL-7 CDA Standard,
visit the link on the screen.
Now, I'd like to switch gears
and offer some general guidance on handling data.
As you know, HealthKit serves as a central repository
where your app and other apps can help contribute
to a user's record of health data.
Your app in cloud service may also have a direct connection
with another app in cloud service,
and this may require some special considerations.
So there are three main topics that I'd like to discuss
when talking about handling data.
First, syncing data.
Second, tracking change data.
And third, migrating data.
So first, syncing data.
You should be using HKAnchoredObjectQuery in order
to handle processing both new and deleted samples in order
to keep up to date with HealthKit.
Anchors act as a bookmark to keep track
of the last query operation you used to fetch data.
You could save this anchor for the next time you need
to create a new HKAnchoredObjectQuery.
You'll open one query for each sample type
that you're interested in
and then pass an optional update handler in order
to continuously process new and deleted samples without needing
to unnecessarily requery HealthKit.
But say for a better user experience,
in order to have fresh UI
when your application is first launched,
or to keep your cloud data in sync, your application needs
to handle processing new and deleted samples even
when it's currently not running.
That's where HKObserverQuery working
with HKAnchoredObjectQuery comes into play.
Let's look at an example with a diagram.
So there are four main steps in order
to handle background updates split
into two phases; setup and execution.
In the first step, we're going to register
for background updates.
You need to do this for every sample type
that you're interested in.
In the second step, you're going to open an ObserverQuery.
Once set up, the ObserverQuery will monitor for both new
and deleted samples in HealthKit.
When new samples are generated,
that's when you have the third step.
You'll get a callback from the observer query
and then execute an HKAnchoredObjectQuery in order
to fetch new and deleted samples.
And then in the fourth step,
you'll call the observer queries completion handler in order
to let HealthKit know that you've processed
and delivered the background update.
You'll then continue to cycle between steps three and four
in order to keep up to date with HealthKit.
Now, let's take a look at this example one by one in code.
So in the first step, we need to register for background updates.
Your application needs to do this every time it's launched,
so we recommend you do it
in application didFinishLaunching WithOptions.
You'll then grab the step's quantity type from HKObjectType
and then pass that to HK Health Store's enableBackgroundDelivery
for, passing in the steps type
and the frequency you'd like updates.
Do note that background delivery times are not guaranteed.
Your application needs to pick the longest possible frequency
it can handle in order
to preserve a user's device's battery life.
Also note that this API is iOS specific.
Background updates are not available on watchOS.
In the second step, we're going to pass the step's quantity type
to create the HKAnchored, the HKObserverQuery.
Here we'll have a custom updateSteps method
that we can use in order to know, to fetch new
and deleted samples when HealthKit detects that.
And then we're going to execute the query.
That completes the setup process in order for HealthKit
to monitor new and deleted samples in HealthKit.
So as I'm walking across stage generating health samples,
step samples, our, we're going to dive
into the update steps method in order to know what we need to do
in order to grab new and deleted samples.
So first, we're going to create an HKAnchoredObjectQuery,
passing in the steps type.
You'll also have predicate, additional fields in order
to filter the particular samples you'd like.
Then we'll call the handleSteps method in order to process new
and deleted samples and then update our anchor
for the next time we need to create an HKAnchoredObjectQuery.
We then call the completionHandler in order
to know that we've done processing fetching new data,
and then we execute the query.
Then lastly, in step four,
we're going to call the completionHandler given to us
from the observer query in order
to let HealthKit know we've both received
and processed the background update.
And that's it.
Now your application will have a fresh UI on launch
and keep your cloud data in sync following all of these steps.
Next, let's talk about tracking change data.
You should be using UUIDs in order
to keep tracking of unique HKObjects.
A unique identifier is set each time an object is created
and persists for the lifetime of the sample.
Record UUIDs in your own data store or both locally
on the device and remotely in the cloud
so that way you could tell a particular sample is the same.
Whenever these samples are deleted, say,
a workout from the Health App, you should be monitoring
for these changes to make sure that these,
those same samples are also deleted again locally
on the device and remotely in the cloud.
And ensure that future sync operations don't re-add already
Now, there are two potential problems that I'd
like to discuss when referring talking
about how to avoid duplication.
The first is pre-populating data.
Pre-populating data is, I'm sorry, onboarding.
Pre-populating data is a great way during on-boarding
to save the user time by pulling information
that may already be stored in HealthKit.
Users have the ability to verify data that's already in HealthKit
and change it if necessary.
However, the problem is saving unchanged values.
Be sure only to save data again if this is the user's intent.
Another additional potential problem may be ingesting data
both from another app and HealthKit.
Remember to only pick one source
of information that's most appropriate to your application.
HealthKit has a great privacy story
that our users have already bought into.
However, you know what's, what source is best for your app.
Make sure not to save another application's data
on their behalf.
Writing only your data once avoids duplicating data
by simplifying which app's responsibility it is
to write it.
There is one particular exception for this rule.
Sometimes duplication is intentional.
For example, if data's coming from multiple sources.
If a data, step data is generated both on a user's phone
and his or her Apple Watch, you can use HKStatisticsQuery
and HKStatisticsCollectionQuery in order
to automatically de-duplicate data by the order
of the preferred data sources that exist in the Health App.
This way, our users get a consistent experience
of the view of their health data throughout our ecosystem.
Now, I want to talk about migrating data.
Let's say that you've launched a new Bluetooth thermometer
and app that writes data into HealthKit.
Your application has been in the App Store for a few days,
but your users discover a problem.
In certain locales, instead of saving 98 degrees Fahrenheit,
you actually save 98 degrees Celsius.
That's a bit warm.
But in this case, we know exactly how we can migrate this
data in order to fix it.
We first need to find old samples, write new samples,
making sure to update UUID stored elsewhere,
and then delete old samples.
Now, a few new things regarding the flow of data
between iPhone and Apple Watch.
Starting in iOS 9.3, data originating
on a user's phone will now sync back to all
of their paired Apple Watches.
Apple Watch is now a reflection
of the most recent health data stored
within the HealthKit ecosystem.
In order to accomplish this,
samples are now periodically pruned based off their end date
on Apple Watch.
Make sure to save samples
after HKHealthStore's earliest permitted sample date in order
to make sure your samples are correctly saved
and synced back to a user's device.
Lastly, sync times are not guaranteed.
You should be saving data on either iPhone
or Apple Watch, not both.
Now, I'm going to hand it back off to Matt, who's going to wrap
up the rest of our session.
Thank you, everyone, and have a great WWDC.
Thank you, Jeff.
Before we wrap up, I'd like to highlight one awesome additional
feature that's brand new in iOS 10 and watchOS 3.
Accessibility is extremely important to use here at Apple.
All of our and your users deserve to enjoy our products
and experiences as much as possible,
and the great activity tracking experience we brought
to Apple Watch is no exception.
iOS 10 and watchOS 3 include great new motion-tracking
features that automatically record data important
to wheelchair users.
And now you can work with and contribute to those types
when you're interacting with HealthKit.
First, there's a new characteristic data type,
HKWheelchairUse that identifies whether the user uses
The value can be yes, no, or indeterminate.
Next, we have some new quantity types specific
to wheelchair users.
Those include wheelchair distance and push count,
which you can think of like step count.
Finally, we have some new workout types important
to wheelchair users as well.
Those include wheelchair walk pace and wheelchair run pace.
When a wheelchair user is using Apple Watch,
the watch automatically records wheelchair pushes
to the new push count data type.
In addition, the stand ring corresponding
to the stand hours data type instead becomes roll hours.
Be aware that wheelchair distance is only automatically
recorded during a wheelchair workout and also be aware
that a user's wheelchair status can change over time.
This is really important
if you're querying for historical data.
In this case, you want to make sure that you query
for both wheelchair types and non-wheelchair types
so that you're not potentially leaving out a big chunk
of the user's historical information.
To sum up, we work really hard to make sure that all
of our products and experiences are accessible to everyone.
You should too.
We strongly encourage you to reach this important segment
of our users by supporting and contributing
to wheelchair data types in your apps.
So we've talked about a lot today.
Authorization is extremely important
for protecting users' privacy,
but getting the user experience right is absolutely key.
Keep authorization in mind when you're developing your app,
and be sure to test it often.
Next, fit in with Apple's health and fitness ecosystem
by incorporating the Activity Rings right into your app
with the Activity Rings API.
Whenever you're interacting with HealthKit,
take care to handle all cases where data is synchronized,
deleted, or duplicated properly to ensure
that your users' data is always precise
and always what you'd expect.
And finally, don't forget to take advantage of the great,
new features we've introduced this year in iOS 10
and watchOS 3, especially wheelchair support,
something we think is extremely important.
If you'd like more information about any
of the things we talked about today
or if you have any questions, please visit this site.
We have lots of additional resources available.
And don't forget to check out our related sessions as well.
We also have these great sessions from previous years
if you want to get up to speed on HealthKit.
Thank you for creating your great apps
that help users live healthier lives
and enjoy the rest of your WWDC.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.