Transcript
[ Music ]
[ Applause ]
>> Good afternoon, I'm Jason
Morley, a software engineer on
the Health Team here at Apple.
And along with my colleague
Peyton I'd like to take some
time to introduce you to an
exciting new feature we have in
iOS 12 this year, access to
health records with HealthKit.
Earlier this year in iOS 11.3 we
introduced Health Records and
Health.
Users can connect to their
healthcare institutions and
securely download their health
records for quick access and
safekeeping.
We aggregate data from multiple
healthcare institutions and
present it in a timeline
allowing users to search and
surfacing important details like
lab values and reference ranges
really helping users to better
understand their health data.
As of today we have support for
more than 500 US hospitals and
clinics covering over 50
healthcare institutions and we
are continuing to add more.
Of course this wouldn't be
possible without the fantastic
standards work of the Health
Level Seven organization with
their fast healthcare
interoperability resources or
FHIR and the Smart health IT
project.
For us it all starts with
health, we establish a secure
connection to healthcare
institutions and download users'
health records in FHIR direct to
their iOS devices.
From here we it store securely
in HealthKit and aggregate data
across multiple institutions.
Starting today in iOS 12 we are
providing APIs to allow you to
access this data and work with
it in your apps.
First, I'm going to introduce
the new sample types that we've
added to support this feature.
Then we can see how you
authorize your application and
query for data.
After that, I'll take a brief
dive into FHIR and show you
what's possible here.
And finally, we can take some
time to think about how you can
help protect your users' privacy
in this sensitive domain.
So let's jump right in.
If you've used HealthKit before
you may be familiar with
HKSampleType and its subclasses.
These group similar types of
data, for example QuantityType
groups data represented by a
single numerical value, things
like step count and heart rate.
While CategoryType groups data
characterized by enumeration,
things like sleep analysis, am I
in bed or asleep or menstrual
flow, heavy or light.
And to support Health Records
we're introducing HKClinicalType
which groups the categories of
health records that you see in
Health, things like conditions
and medications.
Within each of these sample
types the different data types
are differentiated by a type
identifier.
HKClinicalType identifier
identifies the clinical types
that correspond with the
categories of Health Records and
Health.
We have allergies, conditions,
these might be short-term
conditions such as pregnancy or
ongoing conditions like type II
diabetes, immunizations, lab
results, these might be my blood
glucose measurement for my
annual physical.
Medications, procedures, a
diagnostic procedure or a
surgery.
And vital signs, things like
blood pressure or weight.
Alongside these sample types and
sample type identifiers, we're
also introducing a new HK sample
subclass HKClinicalRecord.
If you're not familiar with
working with samples in
HealthKit we have a number of
talks that cover this topic and
I'll provide details of these at
the end.
There are a few key properties
you'll be working with on
HKClinicalRecord.
The clinical type, we looked at
this earlier and this allows you
to determine the type of a given
record.
I want to know that a health
record is for example an
immunization.
We provide a display name which
is a string that we use when
showing that health record to
users in Health.
It's selected from the FHIR
resource and it's your
opportunity to tie back your
app's experience to something
users are familiar with.
You can see in this lab result
that there are a number of
alternative representations and
names, including a coding in the
LOINC coding system.
This is an industry standard
reference for medical
information and it is required
by FHIR for observations.
You can see here that we've
taken that LOINC coding and
performed a lookup to provide a
canonical name which we will
surface to you as the display
name.
And finally, we provide access
to the full FHIR resource, but
there's a lot you can benefit
from looking at the
HKClinicalRecord so I'm going to
set this aside right now and we
can come back to it later.
Like all of Health data,
provenance, or the source of
that data, is very important.
You want to know where this
health record comes from.
And as with the rest of
HealthKit we model this using
HKSource which is available on
the HKSample superclass.
We set the name to be the name
of the healthcare institution
that they have shared with us
and we provide a bundle
identifier which is a stable
identifier for that healthcare
institution across multiple user
logins and devices.
So now we've seen the new sample
types.
Let's see how you authorize your
application and query for data.
As you can see, there's a huge
wealth of information in medical
records and we really believe
that that is a fantastic
opportunity for you to provide
your users with truly empowering
experiences around their health
data.
But of course health records
also contain incredibly
sensitive information.
A user's health records might
contain details of medications
that they are taking or
conditions that they are living
with on a daily basis.
This is information they may not
be comfortable sharing with a
close friend or family member.
And it can change over time as a
user interacts with their
healthcare institution, they
might receive a new diagnosis of
a condition.
So to help our users better
understand and manage access to
that data we're introducing a
new authorization flow specific
to Health Records.
When your app requests
authorization we will present a
new permission sheet specific to
clinical types.
First, we inform users what it
means to share that data with
your app and just how sensitive
it is.
Since we will present this new
authorization flow, whenever you
request authorization you should
ensure that you time your
authorization requests to make
sure your user has sufficient
context with which to understand
this new dialogue.
After this we allow users to
select the types of data that
they choose to share with your
app from the categories that you
have requested.
We also present a new purpose
string and your app's privacy
policy in the app explanation
section.
This is really your opportunity
to explain to users why you need
access to that data, what you're
going to do with it, and how you
will protect that data.
You should be sure to make sure
that what you request is
proportional to what you need.
Users are really going to be
surprised and concerned if they
see types here that don't
pertain to the primary function
of your app.
And finally because data can
change over time as a user
interacts with their healthcare
institution, we're introducing a
new way to control how new data
is shared with your app.
We default to asking before
sharing new data each and every
time.
This means we may need to
present the new permission sheet
whenever new data is available.
So when you need to query for
data you should always request
authorization prior to doing so.
Okay, so how do I get started
and request authorization?
This flow is going to look very
familiar to those of you who've
worked with HealthKit before.
First, I need to configure the
project.
After that request
authorization.
And finally query for data.
To configure your project you
need to add a new health records
capability in Xcode after
enabling HealthKit.
Then you add the new Health
Records Usage Description
purpose string to your
Info.plist.
Again, this is your opportunity
to explain to users why you need
access to this data and what you
will do with it.
Having done this, you can
request authorization.
Here I define the types I wish
to access, conditions,
immunizations, and medications.
And then you can call request
authorization on the Health
Store.
Being sure to handle any errors
and after that you're good to
query.
You should be aware that in
order to maintain user privacy
we don't reveal to you which
categories a user has granted
access or denied access to.
And now to querying.
Because HKClinicalRecord is an
HKSample you can take advantage
of all of the existing sample
query infrastructure in
HealthKit.
Things like SampleQuery,
AnchoredObjectQuery and
ObserverQuery will all work and
if your user has granted
continuous access background
delivery will also work.
Again, you define the type that
you wish to query for.
We're creating a sample query
here and you can execute that on
the Health Store.
So that's the basic
authorization flow.
But we've actually introduced
some additional mechanisms
specific to Health Records.
We have a new API Get Request
Status for Authorization, which
allows you to determine if we
would present a permission sheet
to the user.
This gives you an opportunity to
determine whether your user will
need to see the authorization
sheet and optionally present a
UI to provide them with more
context prior to authorization.
To do this you call Get Request
Status for Authorization on the
Health Store, handle any errors,
and if the request status is
should request you can
optionally present that UI prior
to requesting authorization.
Now there may also be some types
of data that your app requires
access to, to provide a safe
experience or perhaps if you
have a research app you need
access to a comprehensive set of
types to avoid skewed results.
We have a new required types key
in the Info.plist, which allows
you to specify these types.
And if they're present we will
return a new required types
error if the user has not
granted access to these types.
And this allows you to determine
how to behave, optionally
explaining to the user that you
cannot continue if you don't
have this data.
You can implement this by adding
the new required read
authorization key to your
Info.plist.
Here I'm specifying that I
require allergies, conditions
and immunizations.
And then you handle the new
error in the authorization
request.
You should be sure to use this
judiciously and try not to limit
your app's functionality based
on the data that you have access
to.
You really want to make sure as
many users as possible can
benefit from your app
irrespective of how much data
they choose to share.
So that's the full authorization
flow and there's just a couple
of points I'd like to focus on.
Firstly, you should be sure to
request authorization each and
every time that you need access
to data, especially now because
users may want to see that sheet
every time when new data comes
in we may need to present a
sheet when you need to query.
You should also be sure to
request only access to the data
that you need.
And finally, you should consider
taking advantage of the new APIs
to provide users with better
context and allow you to time
those authorization requests.
And with that I'd like to hand
over to my colleague Peyton to
see what he can do with this in
his app.
Thank you.
>> Thanks, Jason.
So I'm working on an app for
mountain climbers training for
their next summit.
I've got a HealthKit powered
view of all my users walking,
hiking and stairclimbing
workouts.
Now after extensive market
research, I've determined that
mountain climbers travel to
mountains and travelers should
know their vaccination status.
So by the transitive property of
future development mountain
climbers should know their
vaccination status.
So I'm going to help out my
users.
I've started implementing a new
tab, an immunization dashboard.
So let me tap on what I have
now.
Here's my immunization dashboard
and to start out with I'm going
to display my users a list of
their current vaccinations and
I'm going to use the
HKClinicalRecords display name
property.
I've already added the Health
Records capability to my project
and I've created a purpose
string to tell my users how I
plan to use their immunizations.
Now it's time to implement my
dashboard.
So here I am at the
ImmunizationsViewController
powering that tab.
In HealthKit it's good practice
to request authorization every
time your user enters the part
of your application using
HealthKit.
So for this app viewWillAppear
is a great place.
Here I need to first specify
that I'm interested in
immunization record samples.
And next, call my Health Store's
requestAuthorization method.
In the callback I'm going to
check for success and handle
errors appropriately.
Finally, once I'm unauthorized
I'm going to call this query for
immunizations method which I'll
implement now.
Here in query for immunizations
I'm going to create a sample
query, I'm going to iterate over
all the return samples, and I'm
going to pass each sample's
display name to my data source.
So let's do that.
Here I've got my sample query
and I'm using the humanization
record sample type.
No predicate because I want all
of the users' immunizations and
similarly no limit because I
want to get all of my users'
immunizations.
No sort descriptors, it doesn't
matter to me in what order these
samples are returned.
And with that I'm going to check
for results and if not handle
errors appropriately.
Next, I'm going to iterate over
the samples and I'll pass them
to my data source by display
name.
With the names in my data source
it's time to head out to the
main queue and call this reload
UI method that I wrote earlier.
Finally, I'm going to execute my
sample query on my Health Store
and that's all it takes, so
let's build and run.
So here I have my training log,
I'm going to tap on my
immunization dashboard tab.
I see the new Health Records
authorization sheet explaining
to my users how my app could
potentially use my users' health
records.
I'm going to tap continue and
here my user has a chance to
allow or deny categories as they
see fit.
There is my purpose string that
I defined in my Info.plist
earlier alongside a link to my
app's privacy policy.
Now users have to explicitly
switch for every single
category, there's no turn on all
button.
So for the purposes of the demo
I'm going to enable
immunizations and to have share
current records.
For future records I'll leave
with the default Ask Before
Sharing and I'll tap done.
And just like that I have a list
of all my users' immunizations.
So that's just--
[ Applause ]
So that's just using display
name, but there's a lot more
information contained in the
clinical records FHIR resources.
So to tell you more about FHIR
I'd like to hand it back to
Jason.
>> Thank you, Peyton.
So Peyton just showed us how we
can request authorization in our
app, query for data, and take
advantage of the new display
name on HKClinicalRecord to
present that information to
users in a way they're familiar.
So now let's take a look at FHIR
and see what you can do with
this rich data format.
Users interact with multiple
healthcare institutions over the
course of their lives and these
are often running different
electronic health record systems
that don't always represent data
in the same way.
This makes interoperability
incredibly difficult.
So to address this the
healthcare community came
together in an effort called the
Argonaut Project, this uses
FHIR, a flexible JSON
representation of health records
and [inaudible] 2 as defined by
the Smart Authorization Guide to
allow connections, consistent
connections to healthcare
institutions and to allow data
to be downloaded in a common
format and related across those
multiple institutions.
FHIR itself models a huge
universe of health data from
allergy intolerance to vision
prescription and it organizes
this data into different data
types called resources.
Each resource has a resource
type and there is one for each
and every kind of health data.
Today we are selecting the eight
most common resource types and
these are defined within the
Argonaut Project and we are
grouping these into the seven
different clinical types that we
saw earlier.
You'll note that we split
observations into lab results
and vital signs based on the
categorization and we group
multiple medication resource
types into the medications
category.
So FHIR represents data as a
JSON dictionary and there are
some key properties that are
present on all FHIR resources.
Things like the resource type,
here we're looking at an
observation and this tells us
that in the context of health
this is a lab result or a vital
sign.
We also have an ID present on
all resource types.
This is a unique identifier for
that resource, but you should
note that it is only unique
within the domain of that
resource type for that
healthcare institution.
One of the most fundamental
building blocks of FHIR is a
coding.
This allows for a reference to a
unique identifier or a code
scoped within an external coding
system.
There are a number of coding
systems specified within FHIR
and you can use these to find
out more about the items that
are referenced in medical
records or to relate specific
things across multiple
healthcare institutions.
Here we're actually looking at a
category coding which tells us
that this is a lab result.
There's also a code in the case
of an observation for what is
being measured.
This is blood glucose as defined
in the LOINC coding system and
it could take that code and look
it up in the LOINC database for
alternative names and further
information.
And of course this is an
observation so I have the value
that is observed.
This is 60 milligrams per
deciliter and you'll note that
even the units here are coded,
so I have a really comprehensive
understanding about what's going
on.
FHIR resources have many
additional data elements and I
encourage you to go and look at
the Argonaut Project
documentation to find out more
and I'll have details of these
at the end.
In HealthKit we model a FHIR
resources as HKFHIRResource.
We provide some key properties
like the data, access to the
full raw data.
We surface common elements like
the resource type and
identifier.
You can access the data using
Swift codable or JSON
serialization.
Here you can see that I've
defined my own codable struct,
my codable observation and I'm
using that to pull out the value
quantity that we saw earlier.
You can have confidence that the
data is structured correctly
here as we only share valid FHIR
resources through the API.
We also introduce some
predicates to make it easier for
you to work with
HKClinicalRecord.
We have a predicate to allow you
to query by resource type, here
I'm looking for prescription or
in FHIR a medication order.
We also have a predicate to
allow you to uniquely identify
records by their source,
resource type and identifier.
This can be incredibly useful as
FHIR resources can reference
other FHIR resources.
For example, a medication might
reference the condition that it
treats.
Now there are some additional
considerations you need to be
aware of when working with FHIR.
Firstly, FHIR resources may
contain their own dates.
For example, prescriptions may
contain the order data of that
prescription while a condition
may contain the onset date,
abatement date and the date that
that prescription is first
observed.
You should therefore use the
FHIR resource directly to access
these dates for each resource
type.
Start date and end date that are
available on the HKSample
superclass are set for the date
that we first add that resource
to Health.
You should use source, resource,
type and identifier when
uniquely identifying a health
record.
This will allow you to identify
a health record across the
course of its lifetime as it is
updated by the healthcare
institution.
And finally, you should be aware
that FHIR and JSON don't fully
agree when it comes to numerical
precision.
FHIR ascribes significance to
the number of digits following
the decimal place and this can
be lost when using Swift codable
or JSON serialization.
If it's really fundamental to
your app that you have full
access to this information Swift
codable and JSON serialization
may not be appropriate tools.
And with that, I'd love to hand
back to Peyton and see what
wonderful things he can do with
this new API.
[ Applause ]
>> Thanks, Jason.
So back to the immunization
dashboard I've been working on.
I'm using HealthKit to fetch my
users' vaccinations, but right
now it's tough for a user to
tell what vaccinations they have
and what they might need to get.
So I'm going to solve that by
implementing an immunization
checklist.
Users can see a summary of their
immunizations in plain language.
To populate this list I need to
know that this combination
vaccine induces immunity against
chickenpox and against MMR.
Health institutions speak
different languages so I can't
rely on name alone, so that's
where the interoperability of
FHIR comes into play.
FHIR gives a way to use
predefined codes rather than
natural language to specify what
things are.
So after taking a look at the
FHIR documentation here's the
algorithm I've come up with to
identify a chickenpox vaccine.
First, I'll take the
immunization records JSON, I'm
going to deserialize it and pull
out the vaccination code in a
system called CVX.
CVX is a commonly used coding
system for immunizations, but
there are many other coding
systems for different areas of
medicine.
Finally, I'm going compare the
CVX code I found in my
immunization record to a list of
vaccines I know induce immunity
against chickenpox.
If there's a match I'll show a
checkmark in my UI next to
chickenpox.
So let's talk about the
immunization record JSON.
The structure starts with a
resource type immunization.
There's a vaccine code object
and contained therein is an
array of codings.
There may be multiple codings,
so I need to search by system to
find CVX.
In this example, the first
system is NDC so I move until I
see CVX.
With that in hand I look at the
code and I look it up and I see
that I have MMRV.
So that's the structure of these
immunization records JSON.
Now it's time to implement.
So here we are back in my
immunizations view controller.
I've done some work ahead of
time to implement the UI of the
checklist and I instantiate it
with a showChecklist property.
Now it's time to populate my
checklist with data.
Here I am in the query for
immunizations method.
When I iterate over my users'
samples I'm going to add a call
to a new method
matchCodedVaccine and I'll pass
it if the sample is FHIR
resource, so let's implement
that now.
Here I am in matchCodedVaccine
from resource and what I need to
do is deserialize the FHIR
resources data, pull out the
vaccination codes, search for
CVX, and compare it against
lists of CVX codes for different
diseases.
I have a lot of freedom in how I
choose to deserialize the FHIR
resource, so today I'm going to
use Swift codables.
I need to define a codable for
exactly the keys that I'm
interested in.
So I've done that now.
An immunization resource has a
vaccine code, a vaccine code has
an array of codings and a
vaccine coding has a system and
a code.
With that I instantiate a JSON
decoder and I use it to decode
the FHIR resources data as an
immunization resource.
All that's left is to iterate
over each coding, check to see
whether the system is CVX, and
then pass the code to this
method to mark it in the data
source.
All this method does is compares
the code against lists of codes
per disease and if there's a
match marks in the UI that
disease for the found disease.
So with that I'm going to build
and run and take a look at my
immunization checklist.
So here I am on my training log,
I'm going to tap on the
Immunizations tab and just like
that with a few lines of code I
have an immunization checklist.
[ Applause ]
So that's an example of solving
a problem using FHIR.
Now for a word on granting
consent for your users I'm going
to hand it back to Jason.
Jason.
[ Applause ]
>> Thanks Peyton.
So Peyton has shown us how we
can take that rich FHIR data and
take advantage of the coding
that's provided to really
provide our users with a very
meaningful and comprehensive
experience around their health
records.
And now I'd like to think a
little bit about how you can
help protect your users' privacy
in this domain.
As you've seen this is
incredibly sensitive data.
We've built privacy in from the
ground up, establishing secure
connections direct to healthcare
institutions.
Downloading data straight to
users' iOS devices.
Storing it securely in
HealthKit.
And providing comprehensive
management tools around access
to that data.
Your users will expect you to
treat their data with that same
level of care and attention.
Every choice that you make here
can have a direct impact on
individuals.
This can be a truly positive
impact and it's why we are
choosing to provide this API
today, but it can also be a
negative one.
If users feel that this data is
out of their control or worse
still, it is shared without
their consent.
You can show respect for your
users and help establish a
relationship of trust by
providing them with clear
policies around that data and
informing them what you do with
it.
This starts with your
application, your purpose
string, and your privacy policy
and it continues every step of
the way as you work with that
data and as you move it around.
For example, you should make
sure you give users details
about how you manage their data.
You should publish clear
retention policies and you
should provide them tools to
allow them to delete that data
should they choose to stop
sharing it with you.
And finally, you should make
sure that you always request
data proportional to your use
case.
You should never be asking for
more data than you need.
I encourage you all to go to the
Privacy Talk, Better Apps
Through Better Privacy on
Thursday at 4 p.m. and this
covers the whole ecosystem, so
it's a great opportunity to find
out more.
So we've seen the new sample
types that we're introducing to
support Health Records.
We understand how to configure
entitlements and privacy strings
in our app, to request
authorization and to query for
data.
Hopefully I have shown you just
enough to whet your appetite to
go and find out more about FHIR.
And we've seen how you can do
more to help protect your users'
privacy.
We continue to be amazed by the
fantastic apps that our
developer community creates and
how it really empowers users
when accessing their health
data.
This is a journey that we
started with Health and
HealthKit and it's one that we
have continued with ResearchKit
and CareKit.
And now today with Health
Records and HealthKit we are
thrilled to be continuing on
that journey with you.
We can't wait to see what
amazing things you do.
You can find the documentation
that I was talking about earlier
at the URL behind me and we have
some labs.
We have a health and fitness lab
immediately after this talk
where we're very happy to get
you started with this new API.
Our colleagues Anherika and
Kareem have a talk tomorrow
morning introducing new ways to
work with workouts.
And we have a health fitness and
research get together tomorrow
night where it's an opportunity
for you all to get to know each
other and talk with us as well,
so please do come along to that.
And with that, thank you very
much and have a fantastic
conference.
[ Applause ]