[ Applause ]
SHANNON TAN: Hello, everyone, welcome to What's New in HealthKit, this is a great opportunity for you to learn about the new things we have in store for you in the SDK this year.
My name is Shannon Tan.
I'm an iOS engineer, and I'll be joined up here in a little while by my colleague Allen Shortlidge.
We are so excited to help you build impactful applications that will help millions of people be more healthy and live better lives.
Let's start with a roadmap of our talk.
Today we will be talking about several different things.
We will go over HealthKit quickly.
We will talk about the unit preferences API introduced in iOS 8.2.
We will talk about the diatribes iOS 9, which will allow whole new aspects of HealthKit-supported software.
Next, Allen will come up and talk about data sources, deletions, and Workout sessions.
Finally we will finish with a WatchKit demo.
Let's talk about some HealthKit background.
Right now, personal health is an extremely exciting area.
There are a lot of apps in the App Store that are focused on helping our users get and stay healthy, and devices like activity trackers and smartwatches are recording large amount of extremely personal and relevant data.
HealthKit is a framework that makes it easier to store and retrieve this information.
It provides a rich set of APIs to save health and fitness data and share between applications while maintaining security with extensive privacy settings and encrypted databases.
What does this mean for you as an app developer?
It means when you use HealthKit you can skip writing custom code to share, store, and sync data and instead focus on features that are core to your app experience while being part of a greater ecosystem.
Finally, with HealthKit comes a Health app, which provides a general view into HealthKit.
In iOS 9 we have added more views to allow to make it easier for users to store, summarize, and correlate their data.
Let's talk about the data types which enable these great Health applications.
Currently in HealthKit there are a lot of data types which cover a wide array of aspects of personal health.
We try to make types that are as expansive and impactful as possible.
One common question is, How does Apple prioritize what data types to add given limited development time?
Our highest priority consideration is the existence of hardware.
For example, there are Bluetooth scales that automatically track weights and Sleeptrackers that measure your sleep activities.
We find the possibility of automatic quantified health data syncing to HealthKit on your device to be powerful.
We also add data types based on existence of software, whether there are popular apps that already exist to create experience around that data type.
Finally, we consider customer and developer feedback.
To support our discussion about data types, let's look at how they are structured.
Every object in HealthKit has a type, and every type inherits an HK object type.
Characteristic types are types that don't change over time, like blood type or date of birth.
Types that do change over time are sample types, and we'll talk about two.
Quantity samples have quantity and unit, like weight.
Category samples can be enumerated into several different values, like sleep analysis.
You can be in one of several sleep states.
Of course, this is a review of already-introduced information.
If you would like to learn more about how HealthKit is structured, we recommend you take a look at last year's talk, Introducing HealthKit.
So I mentioned that quantity samples have a quantity and unit.
I would like to take time now to discuss the new unit preferences API.
Although this API isn't new in iOS 9, it was introduced since our last talk in iOS 8.2.
So we would like to cover it now.
You might have noticed in iOS 8.2 that there was a new unit pane in the Health app.
Units are shown based on the region and locale of a user; however, the user can enter this row and override that default setting with their own unit preference.
In iOS 8.2, there is a new class extension on the HK Health Store that you can use to find this unit preference.
We recommend you do this so that the unit you show in your app UI will match what the user prefers to see in Apple Health.
Finally, there is a new notification that fires whenever this unit preference changes.
Now that we have discussed the units and reviewed data types in HealthKit, let's talk about the new data types available in iOS 9, the first one is water intake.
I'm sure we all know someone who lugs around a gigantic water bottle and when asked, explains that daily hydration is important to well-being and it's probably bad for you to be thirsty all of the time.
There are a lot of apps in the App Store that gently nudge you to increase water intake and even some devices and sensors like Bluetooth water bottles that track your water intake.
A lot of people want to make sure they drink the recommended eight 8-ounce glasses, or two liters, of water a day, or more if they're intensely exercising or if it's a hot day and they're at risk of dehydration.
So we have added new quantity type in HealthKit called Dietary Water.
Its unit is a volume.
Like its name implies, this type can also track water intake that occurs through food.
The next type is UV Exposure.
UV radiation is present in sunlight and it has harms and benefits to human health.
It can stimulate the production of vitamin D, and it can improve mood and well-being.
However, overexposure also has negative effects.
It can have negative effects like sunburn or long-term effects like skin damage or cataracts.
If you spend time in the sun, it may be useful to know when you are most at risk for sun damage.
There are also nifty devices that track a person's exposure to UV rays.
And for apps and sensors that do so, we're adding a new quantity type called UV Exposure.
Its value is a scalar.
It represents the UV index from 0 to 12, from least to most dangerous.
Of course, UV exposure isn't a perfect way to measure your risk of sun damage.
It could depend on the clothing you are wearing, the sunscreen you have on, or the skin type you have.
For the last purpose we have added a new characteristic type in HealthKit called the Fitzpatrick Skin Type.
This represents the skin type of an individual based on the Fitzpatrick scale, which is based on the degree of burning or tanning.
The emogis in iOS 8.3 are based on the Fitzpatrick scale.
All the way on the left is type 1, which represents very pale skin that burns quite easily.
And all the way on the right is dark brown or black skin, which never burns and tans profusely.
Because the Fitzpatrick Skin Type is a characteristic type, it behaves differently from a category or a quantity sample you might be used to.
It's accessed directly against the Health Store, and it returns a simple wrapper around an enumeration.
Now, I'd like to talk to you about a whole new group of data types we are adding under the category of reproductive health.
[ Applause ]
So when we think about quantified health we think about technologically driven items like activity trackers and smartwatches.
We think about HealthKit syncing workouts, or maybe a food diary automatically logging nutrition.
But reproductive health is a major component of health.
For many women who track their health data, nothing has been as exciting or revealing as tracking their menstrual cycles, and for many couples who are trying to conceive and for many couples who are trying not to conceive, monitoring fertile times and understanding hormonal changes or irregularities is critical information.
It might seem strange to talk about data that is so sensitive and so intimate.
Yet when we talk about technology improving lives, this is vital, revealing, and insightful information.
It helps women understand and be more aware of their bodies and to be in control of their health.
It helps and has helped millions of people make informed decisions about their fertility and family planning.
Apps that track cycles in fertility are some of the most popular in the Health and Fitness category in the App Store.
This was the number one developer request for HealthKit.
We are so excited to be adding support for these apps in iOS 9.
So there are many factors to reproductive health, and we starting by adding six new types.
These are meant to be open, so they may be useful for people trying to get pregnant, trying to not get pregnant, or simply people wishing to have a full and more complete picture of their health.
The first type is Basal Body Temperature, and for each type we will be adding a dashboard graphic to show you how we are visualizing this data in Apple Health.
Basal body temperature is the temperature of your body at rest, which typically is measured early in the morning.
It follows a biphasic path where your temperature increases slightly after ovulation.
People often track their basal body temperature for months at a time so they can get a pattern to their cycle and anticipate that the next time around.
It's often measured with a pencil and paper.
It's a time-honored way to track ovulation.
Another popular way to track or to monitor fertility is cervical mucous quality.
As opposed to the change in basal body temperature, the change in CM occurs slightly before ovulation.
In HealthKit, this is a category sample, which lists the generally medically accepted CM states.
The next type we're adding is Ovulation Test Results.
In females, an acute rise in luteinizing hormone triggers ovulation.
A user can buy a home test kit and LH test strips to measure this LH surge.
In HealthKit, this category sample measures the result of such a test, and it can be positive or negative.
Menstruation is an extremely important measure of health.
Doctors often ask women when the date of their last period was and about the regularity of their cycle.
Apps that help people track this are extremely popular and varied.
Here in HealthKit, we are adding it as a category sample.
We are also adding a new metadata key, Menstrual Cycle Starts.
Because the date of your last period and regularity of a cycle is medically important information, we want to make it easier for apps to easily calculate this.
We ask that all clients record this Boolean metadata key, and if we don't see it we will throw an exception.
Let's review metadata.
Metadata is a dictionary that gives additional information about the HealthKit object that helps you extend a given object type and add app-specific information to HealthKit.
The keys to the dictionary are strings that you can create or are that are Apple predefined keys.
Predefined keys facilitate sharing between different applications.
Here we are creating a metadata dictionary that has important information.
And we are putting the sample with the appropriate type of value and passing in that metadata as we're creating the sample before finally saving it to HealthKit.
The next two types will be category samples, but unlike existing category samples in HealthKit, they will only have a single value, HK Category Value Not Applicable.
These category samples have dates, metadata, and other attributes, but they cannot be enumerated into multiple values.
So the first of these types is vaginal spotting.
It refers to light bleeding that occurs outside of the menstruation period.
So it's separate from menstruation.
The second type we're adding is sexual activity.
Sexual activity is relevant and important in many fertility-tracking applications.
And we like to add support for it in HealthKit.
We are adding a new optional predefined metadata key, Sexual Activity Protection Use.
This can refer to protection against STIs or protection against pregnancy.
So let's summarize.
We just talked about the new data types we are adding in iOS 9, Water Intake, UV Exposure, and Fitzpatrick Skin Type, and six new reproductive health types.
We look forward to seeing the new and innovative ways that you will be using these data types in your apps and devices.
Now, I will hand it over to Allen to talk about data sources.
[ Applause ]
ALLEN SHORTLIDGE: Thank you, Shannon.
Hi, my name is Allen, I'm a software developer on the HealthKit team at Apple.
We just heard Shannon discuss the new types of data you can store in HealthKit in iOS 9, and now I would like to tell you a little bit about the new things that you can do with HealthKit in iOS 9.
The first set of changes I will be discussing have to do with sources of data.
HealthKit can store data from a variety of sources.
Samples may be pulled automatically from the Motion code processor in the user's iPhone or from a connected Bluetooth heart rate monitor.
They may also come from manually entered samples in the Health app or saved by applications create by developers like you.
Knowing where the data in HealthKit came from can be important, especially if you are using that data for medical or research purposes.
So how do you tell where data in HealthKit came from?
Well, the HK object class is the root class for all data stored in HealthKit, and in iOS 8 it had two properties related to the source of that data.
The first is the Source property.
And it represents which application saved that object.
The second property is Metadata.
Developers often use metadata to store information about external devices that created objects.
This information can be things like the name of the external device or the manufacturer.
In iOS 9, we are introducing two new properties that give you richer information about where the object came from.
The first of these new properties is the Source Revision property, and it replaces the Source property.
In addition to representing the application that created the sample, it also carries the version of the app that saved the object.
The second property is the Device property, and it returns an object that represents the external device that created the object.
It's intended to replace metadata related to external devices.
Let's take a quick look at the HK Source Revision class.
It just has two properties, the source, which, again, represents oops sorry.
Which represents the application that saves the data, and then it also includes a version string.
When you save an object to HealthKit, HealthKit will automatically assign an HK source revision to it.
The version string comes from the bundle version entry in your app's Info.plist.
Objects that were saved to HealthKit prior to iOS 9 will have a nil version string.
Now, let's talk about HK Device.
HK Device is a class that includes a number of strings that represent different aspects of a hardware device such as its name, manufacturer, version information, and so on.
When you create a device, you will want to provide as many of the applicable properties as possible to give your users and other applications the richest information possible about where the object came from.
If your app saves objects that were generated by the sensors that are built into the device that your app is running on, then you can use the local device class method on HK Device to get a device representing the device that your app is running on.
So let's take a look at how you would save a sample with a device.
First, you will create a device with all of the applicable properties.
Next, instantiate a sample using one of the HK sample subclass initializer methods that takes a device.
Then finally, you can save that object to HealthKit just as you would have previously.
Querying for objects that come from a particular source revision or device is easy too.
You can use one of the new predicate convenience methods exposed on HK Query in iOS 9.
Here is an example of querying for objects that were saved by a previous version of our application.
First, we are creating a source revision with a default source and a 1.0 version string.
Next, we are instantiating a predicate that matches all samples that have that source revision.
Then finally, we will execute an HK sample query, and it will return to us all of the objects that were created by version 1 of our application.
So now that we have talked about new ways to save objects to HealthKit, let's talk a little bit about deleting objects.
In iOS 8, there was one way to delete objects, and that was with the Delete Object method on HK Health Store.
It takes a single object to delete, which is simple, but also a little inconvenient if you need to delete more than one sample at once.
So we are introducing two new convenient ways to delete objects.
The first is a method on HK Health Store that takes an array of objects to delete.
You can use this whenever you have previously queried for a set of samples and you want to delete them all at once.
For example, you might want to migrate samples that were saved by a previous version of your app to use HK Device instead of metadata.
Once you have saved new copies of your previous objects, you could delete all of the old ones using Delete Objects.
The second new method that we are exposing is Delete Objects Of Type with a predicate.
So it will delete all of the objects that match a given predicate.
This is efficient because you don't have to query for the objects before you delete them.
So it's not always the case that you just want to delete objects.
Sometimes you also want to find out about when objects were deleted.
Maybe the user has deleted it or another application.
If your app synchronizes with HealthKit, ideally you would remove an object from your database whenever that object is removed from HealthKit's database.
Within iOS 8, there was no straightforward way to accomplish this.
We are introducing a new way to query for deleted objects in iOS 9 using the HK Anchored Object Query class.
HK Anchored Object Query has a new initializer with a results handler block that has parameters for both new sample and deleted samples.
Now, when you execute this query, HealthKit will return to you all the samples that have either been created or deleted that match your predicate since the last time you ran an anchored object query, which is indicated by the anchor you provide.
Deleted objects are represented by instances of the HK Deleted Object class, which just carries the UID of the object that was deleted.
To save space, deleted objects are only stored in HealthKit for a limited amount of time before they are expunged permanently.
That means if you have functionality that depends on querying for deleted objects, you should register for background updates to guarantee that your app will be launched in response to deletions.
You can use the existing Enable Background Delivery For Type method that exists in iOS 8 to be launched in response to deletions and sample creations in iOS 9.
Now, we are going to return briefly to HK Anchored Object Query to talk about a second new addition we have made to the class in iOS 9.
That's the Update Handler property.
When provided, this block will be called after your results handler whenever there are more samples that have been created or deleted that match your predicate.
An HK anchored object query that has an update handler will continue to run indefinitely until you stop it explicitly with Stop Query on an HK Health Store.
As you will see later in this presentation, this can be an efficient way to process a stream of data from HealthKit.
For instance, you might want to display the user's latest heart rate reading from HealthKit.
You can use an update handler to accomplish this.
As you may be aware, Apple recently released a new piece of hardware, which can detect the wearer's heart rate.
Wouldn't it be cool if you could run this query directly on that device?
Well, it turns out you can.
So in addition to making improvements for HealthKit on iOS 9 this year, we are also bringing the framework to WatchKit apps.
[ Applause ]
So HealthKit on watchOS is a lot like HealthKit on iOS.
Almost all of the HealthKit APIs that you're familiar with are available on watchOS also.
You can store and retrieve health data with all of the same queries and methods that you are used to.
However, because performance is incredibly important on our new platform, only a limited amount of historical HealthKit data is available on the Watch.
We are also introducing brand-new workout APIs that will help you record workouts on the Watch.
Finally, data saved to HealthKit on the Watch will sync automatically to the phone that the user has.
When your app saves a workout on Apple Watch, the energy burned by the user gets counted in their activity rings.
Your users will love getting credit for the exercise that they do while wearing the Watch and using your app.
As you can see in these screenshots, workouts that you save will show up in the Daily Summary and the Activity app on iOS.
Now, before I discuss workouts more, I would like to turn to privacy for a second.
We take the privacy of user's HealthKit data seriously, so naturally we protect it on the Watch just as we do on iOS.
We will need to request access to use the user's HealthKit data.
When your app requests authorization, a prompt will appear on both the Watch and the user's phone to authorize your app for access.
So if your phone application is authorized to store and retrieve distance samples, let's say, then your Watch app also will be authorized to store and retrieve distance samples.
So once you have a WatchKit app that's authorized to use HealthKit data, one thing you might want to do is record a workout.
We are introducing the brand-new HK Workout Session class to facilitate this.
With HK Workout Session, you can specify a type of activity the user is performing, and this information helps Apple Watch more accurately record the user's activity.
While in session, your app stays in the foreground, so whenever the user raises their wrist to check the progress of the workout, your app will be front and center.
Note that only one workout session will be running at any given time.
So if the user starts another workout in another application, then your workout session will end.
Let's look at HK Workout Session.
You instantiate a workout session with an activity type and a location type.
The location type indicates whether the activity is taking place indoors or outdoors.
You can also set a delegate.
This allows you to be informed of changes to the state of the workout.
So the HK Workout Session delegate protocol has two methods.
The first of these is called whenever the state of the workout changes.
For instance, from Not Started to Running or Running to Ended.
It's a good opportunity to note the start and end date of the workout and also start or stop any data queries that you might have.
The second method is called whenever there is an error.
It will be called in addition to the first method, and it indicates that your workout session ended.
Starting and stopping workout sessions is really easy.
You just call Start Workout Session or Stop Workout Session on an HK Health Store.
So now I'd like to give you a quick demonstration of how to build a WatchKit app using these new APIs.
So I have built a simple WatchKit application, and I would like to give you a tour of that app now.
It allows the user to specify an activity that they are performing, like running.
I will choose running.
Once they have chosen an activity type, they will next choose a location type.
Outdoors or indoors.
I will choose outdoors, and this is the in-session view, and it will show a couple of metrics about the workout.
So nothing is happening in this session view because we haven't hooked it up to HealthKit yet.
Let's do that now.
Here in Xcode, we are looking at my activity interface controller.
This is the first view we just saw where the user chose when activity they were performing.
This is a good opportunity for me to request authorization to access HealthKit data.
So I'm going to do that right here in the awake I'm sorry, Will Activate method.
The first thing I have done is instantiate a set of types I want to share which just includes the workout type, and then next, I have a set of types that I would like to read from HealthKit, like active energy burned, distance cycling, distance walking and running, and the heart rate of the user.
Finally, we just call and request authorization to share types just like you would on iOS.
Now, we also need to implement something in our companion application to finish this request.
So I'm in the app delegate of my companion app and I will implement a new UI application delegate method.
Application should request health authorization.
Here all I'm doing is calling handle authorization for extension with completion, which will prompt the user to authorize my app.
Let's see this in action now.
So as you can see, the user has been prompted on both the Watch and the phone to open your app and authorize the app.
Here is the familiar health authorization sheet.
I will approve the app to access everything it wants to, and hit Allow.
Now, we are authorized to use HealthKit data.
So the next thing we need to do is start a workout session when the user taps Start.
I have a Workout Session Manager class here, and that's what is responsible for managing my interaction with HealthKit.
It's a bit of a big class, but we are going to implement just a few parts of it.
The Start Workout method is called right here when we hit the Start button.
So I will want to start a workout session which I have instantiated previously in my constructor.
All we are doing is calling Start Workout Session on an HK Health Store with that workout session.
Now, we need to implement the workout session delegate protocol so that we can be informed of changes to the state of the workout.
So as this is called on a background cue, I'm dispatching back to the main queue before handling the state change.
If the state of the session changed to Running, I will call my Workout Did Start method, and if it changes to Ended, I will call Workout Did End.
So let's go down to Workout Did Start.
One of the things we will need to do is start some queries for HealthKit data to display in the workout.
One of those metrics is distance.
So I need a query for gathering distance data from HealthKit and accumulating it as the workout session progresses.
I'm going to create a helper method that will create that query right here, and we are going to use HK Anchored Object Query with an update handler.
So I have written Create Streaming Distance Query, and it takes a workout start date.
The first thing we do is create a predicate, which matches all queries that, sorry, matches all samples that have a start date after the workout start date.
Next, I have instantiated an HK anchored object query with a results handler that calls my Add Distance Samples method.
Add Distance Samples is implemented right here.
It dispatches back to the main cue and then it adds the new distance sample to my running total of distance and it also adds that sample to an array of samples that I'm accumulating over the course of the workout.
So, again, in the results handler we call Add Distance Samples, and then in our update handler, we do exactly the same thing, and finally we return that distance query.
So now that we have that available to us, let's use it in Workout Did Start.
Workout Did Start notes the start date of the workout, and then it creates queries for streaming distance, active energy, and heart rate.
It executes all of the queries that we created, and then it informs the UI that the workout started.
So let's take a look at how this works now.
So I will choose running again.
An outdoor run.
And as you can see, the timer is increasing, and I'm also accumulating some simulated distance samples, and some calorie samples will show up in a little bit.
So the user can see their distance, calories, and heart rate right here in the app.
The last thing that we want to enable the user to do is to stop and save the workout.
I have a Force Touch menu that just has a single Save button that the user will tap when the workout stops.
We haven't implemented this yet, so the workout is still continuing though.
So now let's implement that.
So I have a Stop Workout And Save method that's called by the UI whenever the user taps that Force Touch menu button.
I will stop the workout session here.
And I do that just by calling Stop Workout Session.
Now, we need to handle that state change to the ended state.
We are calling Workout Did End in response to that.
So here, as you might imagine, we need to stop our queries and then save the workout.
So we will note the end date of the workout.
We will stop all of our queries.
We will inform the UI that the workout stopped, and then we will save the workout.
Saving the workout to HealthKit is pretty simple, too.
The first thing I have done is unwrap the optional start and end dates that I noted in Workout Did Start and Workout Did End.
I am using Swift's new guard statement to return early if those are nil.
Next, we instantiate a workout with the activity type that the user performs, the start and end date, and the total active energy burned and distance.
I'm also creating an array with all of the samples that I accumulated over the course of the workout, because we want to associate these samples with it after we save the workout.
Next, I will save the workout to HealthKit, and once that's complete, I will add samples to that workout.
So let's take a look at that now.
So I'm choosing running again, outdoor run, my workout is progressing.
Once we have got a few metrics here, I'm going to save it.
And I will save it.
And the workout is finished.
So now that we have saved that workout to HealthKit, let's see if we can get it to show up in our companion app.
There is our three-calorie workout right there.
It was a lot of work.
[ Applause ]
Okay. Let's recap what we did in the demo just now.
First, we requested authorization to access the user's HealthKit data.
Next, we used HK Workout Session to record the workout and we streamed samples from HealthKit using HK Anchored Object Query.
Finally we saved the HK workout to HealthKit and associated samples with it.
So that's what's new in HealthKit in iOS 9.
We started today by covering the unit preference API, which allows you to display HealthKit data in your app using the units that the user prefers.
Next, we covered new data types that you can store in HealthKit such as Water Intake, UV Exposure, and information related to reproductive health.
Next, we talked about source revisions and devices, which give you a richer picture of where the data in HealthKit comes from.
We also covered new ways to delete samples and query for deleted samples.
And finally, we discussed the HK Workout Session API and showed you how to build a WatchKit app that uses it.
We think you will love the improvements we made to HealthKit in iOS 9 and we can't wait to see what you build with it.
For more information, you can visit the developer documentation at developer.apple.com/healthKit or contact technical support.
You can make a general query to email@example.com.
So thanks, and enjoy the rest of the conference.
[ Applause ]