HealthKit provides robust tools for building great workout apps for Apple Watch. Learn how your workout app can collect data from Watch sensors, run and analyze data in real-time in the background, and contribute to Activity rings. Gain insights into creating a great standalone Watch experience and see how to display your workouts within the Health app and the Activity app on iOS.
Welcome to Building Great Workout Apps.
You are here because you care
about building the best experiences
for users of your fitness apps.
Some of them are fanatical.
They're spending hours per week on their fitness,
and they expect responsive, easy to use apps
that provide accurate data
and integrate seamlessly with Apple Health.
My name is Dash.
I'm an engineer on Apple's Health and Fitness team,
and I'll be joined up here in a little while
by my colleague Jorge.
Today, we're going to show you how to build great workout apps
that your users will love.
Working out is an important aspect of overall health.
It can help you sleep, make good eating decisions,
and clear your mind.
Many of you have worked hard to create workout apps on iOS
that inspire users to track their fitness activities
and reach for new health and fitness goals.
With Apple Watch, workout apps come to life
within the moment heart rate, calorie burn,
and activity detection,
in an experience delivered exclusively from the wrist.
Today, we're going to primarily focus on how
to build great workout apps for Apple Watch.
We'll start by introducing background running,
a new game changing capability for workout apps on watchOS 3.
Then, we'll walk through the lifecycle
of a workout from start to finish.
Along the way, we'll show you how your workout app can
contribute to the user's activity ranks.
Next, we'll discuss some new APIs that we've added
for workouts in iOS 10.
And finally, we'll review some best practices.
So let's get started.
At the core of every workout app is a workout session
that the user can start and stop.
So we start with HKWorkoutSession.
This API is simple to use
and provides automatic benefits to your workout app.
When a workout session is active,
the sensors on Apple Watch will use the activity type
of the session to accurately compute motion and calorimetry.
This will also enable your app to contribute
to the user's activity rings.
For example, during a workout,
activity will use the workout type to award exercise minutes
to the user's exercise ring.
During a workout session,
your app will be displayed whenever the user wakes
Users will love having instant access
to your app while they're using it to workout.
Finally, we're really excited to announce that workout apps
in watchOS 3 can now be set up to run in the background.
Let's talk more about background running.
Background running will elevate the experience
of your workout app.
Your app will be able to process data
from the sensors in the background.
For example, you'll be able
to receive continuous heart rate values even
when your app isn't displayed on screen.
You'll also be able to provide live feedback to the user
at any time during the workout session.
You can send the user haptic alerts
to let them know their current progress.
This will also allow you to quickly show
up to date data whenever the user just glances
at their wrist.
Enabling background running is simple,
just add workout-processing to the BackgroundModes
in your extensions Info.plist.
Of course, to maintain high performance on Apple Watch,
it's critical that you limit your background work
to only do what's necessary.
If your app uses excessive CPU while in the background,
watchOS may decide to suspend it.
We recommend that you use our tools
to measure your app's background CPU usage.
You can use the CPU report tool in Xcode,
or the time profiler in instruments.
watchOS 3 will also generate a log
with a backtrace whenever your app crosses the CPU threshold.
Now that you're set up for background running,
let's walk through the steps for starting a workout.
There are three steps for starting a workout.
First, you need to request authorization
to access data in HealthKit.
Second, you'll create a workout configuration object
representing the type of workout that you'd like to start.
And third, you'll create
and start a workout session using your
Let's go through these one-by-one.
All workout apps will want to request authorization
to write workouts to HealthKit.
This will enable workouts from your app to show
up in the user's health and activity apps.
Depending on the specifics of your workout app, you may want
to request authorization to read energy burned,
distance, and a heart rate.
If you'd like more information on how to set up authorization,
we recommend you take a look at our previous talk,
Getting the Most out of HealthKit.
Workout sessions are created
with a workoutConfiguration object.
The workoutConfiguration includes the workouts activity
type, such as running or bicycling,
and the location type, such as indoor or outdoor.
You will use the configuration object
to create a workoutSession, then to start the session,
simply pass it to the start method on an HK healthStore.
Let's try this out with a demo.
For just today, let's pretend we all work for the same company.
Our latest project is to build a workout app
for watchOS 3 that's designed specifically for sloth lovers.
It's called SpeedySloth.
I've an Xcode project here
that already has the UI built for this workout app.
Let's take a look together.
So this is the first view that the user sees
when they open our app.
It has two pickers, one for activity type,
which can be walking, running, or hiking.
And another for location type,
which can be outdoor, indoor, or unknown.
When I press the Start button, nothing happens.
Let's fix that together.
The view that you just saw is controlled
by a class called configuration interface controller.
I've a method right here called didTap StartButton,
that's called whenever the user taps the Start button.
I'll fill it in now.
I'm creating a workoutConfiguration object,
and I'm setting the activity type
to be the currently selected activity type
from that first picker.
Then I'm setting the location type
to be the currently selected location type
from that second picker.
I'm passing the workoutConfiguration object
to a new interface controller called
WorkoutInterface Controller is responsible
for managing the UI during our workout session.
It will also be responsible for Starting
and stopping the workout session.
Let's take a look at WorkoutInterface Controller.
So, I'm in the awake method of WorkoutInterface Controller,
and I know that we'll receive our workoutConfiguration object
as a context object in this method.
Let's use it to start a workout session.
First, I'm unwrapping the context object to make sure
that it's a valid workout configuration.
Then I'm using it to create a workout session by passing it
to the initializer for HKWorkoutSession.
I'm setting the delegate of my workout session to be self,
so we'll receive callbacks for things
like state changes and errors.
Then I'm saving the current date to be our workout start date.
We'll use this later on, when we save our workout sample
Next, I'm passing the workoutSession
to the start method on HK healthStore.
Let's try it out.
So here we are at configuration interface controller.
I'm going to leave it at outdoor walk and I'm going
to press the Start button again.
So this just opened WorkoutInterface Controller.
So I've a feeling, that our workout session did start
correctly, but to be sure, let's take a look
at the clock face on the device.
You'll see at the top,
that there's a green running man icon.
This indicates that one of the apps
on this watch has an active workout session.
The user can tap this at any time to get back to the app
with the active session.
So it looks like our session did indeed start correctly.
Let's review what we just did.
We used information from the user
to create a workoutConfiguration object.
Then we used that configuration to create a workout session.
And we started the session by passing it
to the start method on our healthStore.
Now that we have an active workout session,
we want to start collecting some data to display
to the user during the workout.
To talk to you more about data collection and control,
I'd like to invite up my colleague Jorge.
Thank you Dash.
My name is Jorge.
I'm a software engineer in the HealthKit Team.
So, my colleague Dash just showed you how to configure
and start a workout session.
Now, we are going to continue
by discussing how you can collect data
and control the state of your session during a workout.
We are going to be calling data collection
and control those different tasks that you need to perform
from the moment you start a workout session
and until you decide to end it.
Let's take a look at all these different steps.
First, we are going to be observing samples, that is,
retrieving sample information from HealthKit in order
to incorporate those into your workout.
Next, we are going to be observing events.
Events can be generated by HealthKit or you can detect them
from your user interface.
We're going to be discussing events a little more
in detail later.
Once you started those two tasks,
you're in a running state.
At any point, you could choose to pause,
and then resume the workout maybe several times.
And later, you will decide that you want
to end your workout session.
So let's take a look
at all these steps a little more in detail.
First, we said we wanted to observe samples.
The way you do this is by opening an anchor object query
for each of the data tabs you're interested in.
That could be, maybe, wheelchair distance,
or it could be active energy burn.
When you do this, you also will setup an updateHandler in order
to receive new event, new samples arriving to HealthKit.
That will allow you to keep running totals for your workout
such as maybe the total accumulate distance
or total accumulated number of calories.
With that, you will be able to update your UI live.
You will also be able to display, for example,
the most recent heart rate measured.
You could also notify users of certain goals, for example,
whenever they reach the first mile in their run,
or whenever they burn the first 100 calories
in their rowing workout.
So let's now take a look at some code.
Since we are going to be using anchor object queries,
the first thing that you need to do is
to create a predicate for your query.
We are going to start by using the start date of your workout.
You do not want samples that the work generated before that date
to count against your totals.
Next, you're going to be asking for samples
from the local device.
That means the current watch.
You want to avoid, for example, getting samples
that are being saved on your watch as a result
of a sync operation with your iPhone.
Finally, you're going to compose those two predicates
into the final predicate you're going to be using in your query.
Next, you have to set up a handler in order
to process samples arriving in from HealthKit.
You will normally accumulate those samples into your totals
and maybe display some updated user interface.
Now, we are ready to create the anchor object query.
You're going to be using the quantityType you're interested
in, the predicate we just built,
and set up your initial results handler
as the handle we defined before.
You will also set up the updateHandler
so you get new samples arriving
to HealthKit during your workout.
Finally, you're going to execute your anchor object query.
We also mention that you would like to notify your users
of certain reached goals.
For example, whenever they reach the first mile,
or the first 100 calories in their workout.
The way you will normally do this, is like playing a haptic
to alert the user of this situation.
When you do that, we recommend
that you update your user interface
so you reflect what this reached goal is.
It is very likely when a user feels the haptic,
they will raise their wrist and try to see on the screen,
what this haptic was about.
The way to play a haptic is by using the play method
in WatchKit interface device.
Now let's talk about events.
Events are timestamps you would use
to highlight certain points during your workout.
For example, you can use pause and resume events
to highlight the point where your workout state changed.
Some events are going to be created by your application
and saved later into your workout.
Others are going to be created by HealthKit and sent to you.
New in watchOS 3, we have the didGenerate event
in workout session delegate that HealthKit will use
to send events to your application.
So let's now take a look at the different types of events
that we have in watchOS 3.
Laps and markers are two new events that we just introduced.
These are events that you want to create yourself
to store in your workout.
This will represent timestamps you can use later
for displaying your workouts in graphs or statistics.
There is a difference between laps and markers.
Laps represent events that partition your workout
in equal distance portion.
For example, if you're in a running or cycling workout
in a track, you would create a lap event each time the user
completes a round.
Markers, on the other side,
can be arbitrary points in your workout.
They don't have to be tied to distance or to any other metric.
They could represent, for example,
the moment your user reached the top of a hill,
or maybe that time where you saw a sloth in your way.
Now let's talk about pausing and resuming workouts.
During a workout session, your user might decide
to momentarily stop the activity.
For example, they are on a run, and they might decide to stop
to buy a bottle of water.
In this case, you will have some way in your user interface
for your user to let you know of this situation.
When this happens, you can now call into HealthKit
to pause your workout.
This will allow HealthKit to save power on your watch
and space in the database.
Of course, when this happens, you want to ignore any new data
that arrives to your application.
You don't want to accumulate samples
to your totals while your session is paused.
HealthKit will respond to pause and resume calls
by generating pause and your resume events
that you will get using the workout session delegate.
It's important to know that after you receive a pause event,
no new events will be generated by HealthKit,
until you resume your session.
New in watchOS 3, the function you will use to pause
and resume your workout are part of HKHealthStore,
pause workoutSession and resume workoutSession.
Events that you will receive are paused and resumed,
which you may already know from previous iOS releases.
Now let's talk about motion events.
This is new in watchOS 3.
The motion pause and motion resume events.
Your watch, during a running workout, is able to detect
that the user stopped moving.
That means they are not running anymore.
And we will be able to detect whenever they start
When you receive these events, you will stop collecting data
into your workout, the same way as you did
when the user manually paused.
However, you do not need to pause your workout session.
Note that this is implemented only
for the running activity type.
So let's go back into our SpeedySloth demo application
and see how we can incorporate some
of the concepts we just learned about.
So I'm going to be switching to our demo.
So to recap what we saw before, we have our workout application,
which already started our workout session, but we can see
on the screen that calories and meters reported as zero.
We are not accumulating data yet.
So let's go into our workout and see how we can fix that.
So going back to our workout interface controller class,
I'm going to be looking for the delegated callback
when decision changes it state.
This is workoutSession didChangeTo toState fromState.
Here I have switch statement which is empty for all cases.
What I'm interested in right now is the running case.
Whenever we came from a notStarted state that means
that the application just started the workout.
So if you are in the running case and coming from notStarted,
I'm going to be calling a function called
So let's take a look at this function.
What we want to do is to update those two labels that we saw
on the screen, one for your distance,
and another one for your energy burn.
So basically we are going to be starting two queries for each
of those two data types.
The way you start the query is exactly what we saw during
We first are going
to be building a predicate to use in your query.
Next, we are going to be defining a handler.
In this case, I already have implemented process function
that will grab those samples, accumulate those,
and update my user interface.
Now, I'm ready to create my query,
set up the updateHandler and execute it.
And finally, what I want to do is to save that query for later.
Because a query executed with an updateHandler,
we want to stop it at some point.
So let's now go and run our application again.
Switch to the simulator.
Okay. Here we are.
So we are going to be choosing, let's say,
a running outdoor workout.
There it is.
When we start, we can see
that we see some numbers increasing on the screen.
This is because the watch's simulator is generating some
fake samples for you whenever you start a workout session.
Great. So if you take a look at the screen,
we see there are several buttons,
but they are currently not doing anything.
We already discussed how you can pause and generate marker events
for your app, so let's go into the code
and see how we can do that.
So here I have the didTapPause ResumeButton function,
but it's hooked up to the Pause button on the screen,
so I'm going to be inserting some code here.
First I'm going to be checking that I have a workout session,
and I'm going to be checking the state of it.
If it's running, I'm going to be pausing the workout session.
If it's paused, I'm going to be resuming it.
Good. As a result of this,
your workout session will change state, so if we go back up
to the delegate callback,
whenever your workout session changes to some certain states,
you're going to see here that the paused state is empty,
so we're going to be inserting some code.
In this case I already have implemented
pauseAccumulatingData, which is a function
that will basically stop considering new samples
as they arrive into the totals of my workout.
Similarly, we need to resume the workout at some point,
so whenever our session goes back to running state,
we're going to receive resumeAccumulatingData.
The other button that we have
on the screen was the Marker button.
In this case, what we are wanting
to do is create a markerEvent.
We just create the workout event
with a marker type and the current date.
We're going to be saving that event into a local array
for later saving into our workout.
And finally, I have a step here that will notify the user
on the user interface.
This event just happened.
Also note that we already have implemented the didGenerate
event that is a callback from our workout session delegate.
In this case, we also want to save the event generated
by HealthKit into the workout events array.
So let's now run our application again.
Give it a second for it to launch.
Okay. Here it is.
I'm going to choose Walking Outdoor now.
And give it a few seconds
so we can have some numbers on the screen.
You can see at the top of the screen that it says
that there is an active workout.
Whenever I hit the Pause button, it goes into pause state
and you can see that the numbers are not incremented
for calories and meters.
I can probably resume it right now.
It goes into active state, and the numbers increase again.
You can also tap on the Marker button,
which it basically displays something the user interface.
It is very likely that an actual watch you can also play a haptic
for your user.
Great. So let's now switch back to our presentation.
So let's recap what we saw.
We just saw how you can use anchor object queries
to get information from HealthKit
and update your workout totals.
Then we implemented pause and resume events
in your workout application, and finally, we show you how
to create an event and save it for later.
Next step will be ending your workout session.
To talk about that, I'm going
to invite my colleague Dash again on stage.
Ending and saving a workout is simple.
With a few steps, workouts saved
from your app will integrate seamlessly
with the activity and health apps.
Let's take a look at the activity app now.
Workouts saved to HealthKit will automatically show
up in the activity apps workout list.
Starting in iOS 10,
this includes workouts saved on the phone.
This means that a user can do a workout in an app on their phone
when their watch isn't even nearby,
and they'll still get credit in the activity app.
Workouts saved with energy samples will be able
to contribute to the users move ring.
Users will love getting credit from working out in your app
in their activity day.
Let's walk through the steps to end and save a workout
so that it shows up in the user's activity app.
There are three steps to completing a workout.
First, you end the workout session.
Second, you save the workout to HealthKit.
And third, you add related samples to the saved workout,
such as energy burned and distance.
Let's go through these one at a time.
To end the workout session, you simply call end
on your healthStore, and pass along the workout session.
This will reset the devices sensors to their normal mode.
When HealthKit finishes ending your workout,
your workout session delegate will receive a callback
in its state change method.
When you see that the state has changed to ended,
it's time to save the workout.
You'll create an HKWorkout sample to save to HealthKit.
The information that you create your workout
with will be displayed in the user's health and activity apps.
Make sure to use the same activity type that you used
on your workout configuration.
Set a startDate and an endDate for the workout,
and include an array of workout events.
This array can include events like pausing and resuming,
and markers or laps as Jorge discussed earlier on.
The totalEnergyBurned value is an HK quantity
that represents the sum
of all energy burned during the workout session.
Likewise, the totalDistance value is an HK quantity
that represents all distance traveled during the
Finally, don't forget to add metadata.
Set a value for the IndoorWorkout key
to indicate the location type of your workout.
You can save this workout sample to HealthKit simply
by passing it to the save method on your healthStore.
When you see that it's been successfully saved,
it's time to add samples to the workout.
Let's talk more about adding samples.
When you add samples to a workout,
HealthKit creates an association between these samples
and the workout itself.
Apps will be able to query later on for all samples
that are associated with a given workout.
This will be useful if you want to graph detailed data
across your workout timeline.
Adding energy samples to the workout is necessary
if you want the user to get credit
in their activity move ring.
Activity will use these associated energy samples
to compute credit for that ring.
Finally, make sure that the totals stored previously
on your workout sample match the sum
of all these associated samples.
To add samples to your workout, simply pass an array
of HK samples to the add samples
to workout method on your healthStore.
Let's update SpeedySloth now to include ending
and saving the workout.
So when we were last in the app, Jorge showed us how
to collect data to display to the user.
And also how to control the event by pausing and resuming.
You may have noticed at the bottom
of the Workout Interface Controller,
that there's this button called End Workout.
When I tap it, it doesn't do anything yet.
So we'll fix that now.
I'm back in Workout Interface Controller,
and I have a method called didTapEndButton.
Let's fill it in.
First, I'm saving the current date to be our workoutEndDate.
We'll use this in just a second
when we create that workout sample.
Next, I'm calling the end method on my healthStore
and passing along the workout session.
When HealthKit finishes ending the session,
we can expect a callback in our state change method.
I'll go back to this state change method now.
So Jorge showed us earlier,
how to handle the running and pause states.
Now we want to handle this ended state.
We want to do two things when the workout session is ended.
First, we want to stop all the queries.
This method is already implemented and it just iterates
over the array of open queries and calls stop for each one.
Next, we want to save the workout.
Let's implement that now.
I'm creating a workout sample
and I'm using the activity type straight
from our workout configuration.
Then I'm setting the start date and the end date
that we saved earlier on.
I'm including the array of workoutEvents
that Jorge showed us how
to build during the workout session.
I'm using the quantities for totalEnergyBurned
and totalDistance that we accumulated
from our data queries during the session.
And finally, I'm including a dictionary for metadata.
I'm setting the indoor workout key to have a value based
on the location type of our workout configuration.
I'm passing this workout sample to the save method
on my healthStore, which will save it to HealthKit.
When I see that it's successfully saved,
I'm going to call addSamples toWorkout,
which is a function right down here that we'll implement now.
I want to add two samples to this workout,
one for totalEnergyBurned, and one for totalDistance.
For totalEnergyBurned, I'm creating a quantitySample
and I'm using the quantityType active energy burned.
Then I'm passing the same totalEnergyBurned quantity
that I used on my workout sample.
This means that there will be one big energy burned sample
that spans the entire duration of the workout.
If you'd like to, you can create multiple smaller energy burned
samples, just make sure that they sum to the same total
that you set on the HKWorkout sample.
I'm doing the same thing for the totalDistanceSample.
I'm using the quantity type distanceWalkingRunning.
HealthKit has three distance types.
I'm using WalkingRunning because our workout app only handles
walking and running distance.
If you're building a cycling workout app,
you'd want to use cycling distance,
and we've also just added a new distance type,
wheelchair distance, that you would use
for wheelchair based workouts.
I'm using the same total distance quantity that I used
on the workout sample, and I'm setting the same workout start
and end date.
So again, this is one big distance sample
that spans the duration of the workout.
I'm adding these two samples to the workout by passing them
in an array to the add samples
to workout method on my healthStore.
When I see that they've been successfully added,
I know that all my data for this workout is stored in HealthKit.
Now I want to display that workout to the user.
I'm doing this by passing the HKWorkout object
to a new interface controller called
SummaryInterface Controller is already built and knows how
to display an HKWorkout to the user in a summary view.
I'm going to run the app again,
and we'll see how to end our workout.
Let's do outdoor run again.
I'll press Start.
And we'll wait a few moments for some data to collect.
Okay I'm going to press the End Workout button now
because we have some data.
Our workout session was ended
and our sample was stored in HealthKit.
Here's the summary view displaying
that workout sample to us now.
To make sure that it did indeed store properly in HealthKit,
let's take a look at the Health app on the iPhone simulator.
Here I am in the Workouts view of the Health app.
I'm going to tap Show All Data to see a list
of all of our workouts.
At the top you can see a workout
that was just completed at 11:36.
That's our workout.
I'm going to tap it to see more information about it.
So you can see that this is the running workout.
It had an almost 13 second duration,
and there's our start and end date.
This is all the information from our workout sample.
You can even see the metadata down here
that says it's not an indoor workout.
At the bottom, you can see those two samples
that we associated with the workout.
We have almost two calories for a total energy burn.
Good job everyone.
And we have a 100th of a mile.
So looks like everything did save to HealthKit correctly.
Let's review what we just did.
We ended our workout session by calling end on our healthStore.
And then we waited for our callback
in our state change delegate method.
When we saw that the state changed to ended,
we created a workout sample and saved it to HealthKit.
Then, we created two samples to add to the workout,
one for totalEnergyBurned, and one for totalDistance.
Remember associating that energy burned sample is necessary
so that the user will get credit in their activity ring.
So we've just built an entire workout app for watchOS 3.
It's that simple.
Now every app on WatchOS comes
with a parent application on iOS.
So we've added some new API's
in iOS 10 specifically for workout apps.
To talk to you more about these new API's I'd
like to invite Jorge back up.
Thank you, Dash.
So you've been developing great applications for your iPhone.
So workout apps are not only about your watch.
Starting on iOS 10,
we are providing some new API's you can use
to implement new functionality in your iPhone applications.
We mentioned that every watch application comes
with a parent iPhone app.
You can use that to your advantage
to build great experiences for your users.
You might already be using WatchConnectivity for messaging
between the two applications.
This is an effective way
of implementing features while your watch is in a workout,
and the application is running.
Now we have background running,
so your application can be running all the time.
That allows you to implement great new functionalities.
However, in order for this to happen,
you need to have your watch in the workout state.
So, starting with iOS 10, we're providing functionality
where you can start a workout from iPhone.
That is, your watch will be in a workout state,
without the user having to intervene in its user interface.
So, let's take a look at how this works.
On your iPhone application, you will select an activity type
and a location, and you will create a
Once you have that, you send that workoutConfiguration object
to the watch application.
If the watch application is not already running,
it will be launched for you.
Now, the workout application can grab that configuration
and start a workout session.
In order for this to work,
you need to have the workout processing background mode we
mentioned earlier in this presentation.
So let's now take a look at some code.
You may be familiar with this code
because we saw it earlier in this presentation.
This is what you do whenever you want
to start a workout on your watch.
You first create a workoutConfiguration object,
and then use that to create a workoutSession and start date.
In this case, we want to separate this code in two parts.
The first part, creating the workoutConfiguration,
will be executed on your iPhone application.
Creating a workoutSession
and start date will be executed on the watch app.
For this to work, you need some sort of communicate
between the two applications, so let's first take a look
at the iPhone application code.
First, you need to check with WatchConnectivity
if you have an activated session,
and if you have a watch application installed.
Once you do that, you're ready
to create your workoutConfiguration.
Next, in order to pass this workoutConfiguration
to your watch application, you're going to be calling
in the new in iOS 10 startWatchApp
which is a new method of HK healthStore.
This will grab your workoutConfiguration and send it
over to your watch app.
So let's now look at the watch application code.
What you want to do is grab that workoutConfiguration
to create a session and start it.
For that, you will implement handle workoutConfiguration,
which is a new function, which is part
of WatchKit ExtensionDelegate.
By implementing this function,
you will grab your workouConfiguration
and are ready to start it.
So, let's now go back into our SpeedySloth demo app,
and see how we can actually start our workout
from your iPhone.
So, let's take a look at our iPhone simulator.
I'm going to create the health app.
And here I have the iPhone version
of our SpeedySloth application.
So I'm going to launch it,
and you see that the user interface looks very similar
to what we did on the watch.
We have a user interface that allows you
to select an Activity Type, and a Location Type.
And then we have a Start button
that is currently not doing anything.
So let's take a look at our code
and see how we can actually implement that functionality.
So I'm going to be switching to the code
for the iPhone application
and I have configuration view controller which is the class
that handles that screen that we just saw.
In the didTapStart button,
we're going to be implementing our functionality.
First, we're going
to be creating our workoutConfiguration object
with the selected activity types and location.
This is the exact same code that we have on the watch app.
Next, we are going
to be grabbing our workoutViewController
for our storyboard.
This is the UI that we're going
to show while the workout is running.
We are going to set the property of workoutViewController
in order to pass the workoutConfiguration we created.
And finally, we are going to be presenting that user interface.
So let's take a look at workoutViewController code,
and see what it is doing.
On the viewDidLoad method, we see that the first thing
that we do is to initializewatch Connectivity.
This is basically grabbing our WatchConnectivity session
and make sure it's initialized.
Then, we are going to be calling into startWatchApp function.
The startWatchApp function is going to first check
that we have a valid workoutConfiguration
that we have a valid WatchConnectivity session,
and then this is the same code that we saw in our slides.
We first check that the connectivity session is
activated and that we have our watch app installed.
Finally, we are going to be calling in to startWatchApp
Great. So now we have to go into our WatchKit extension
to make sure that we grab that workoutConfiguration object.
So, we are going to be moving into the workout --
into the ExtensionDelegate for the watch app,
and using the same code to handle the workoutConfiguration.
When we do that, we want to wrap that workoutConfiguration
in a context object and pass to the Workout InterfaceController.
This is the same user interface
that we were showing whenever you started a workout
on the watch.
One other thing that we want to note here, if we're going
to Workout InterfaceController, whenever an application --
let me see -- whenever I said an active workout session
We're going to be calling this updateState function.
This is something that we already have implemented
in our code, which is basically going to grab the current state
of the session, and send in through WatchConnectivity
to the iPhone application.
So, let's now run our code switching to the iPhone app,
and take a look.
There it is.
So we are going to be selecting outdoor walking workout.
When I press the Start button,
you see the workout session is starting.
If you go back to the watch simulator,
you see that the app launch, and it's now workout state.
Going back to the iPhone app, you can see that now it is
in running state, if you missed that,
I can probably pause the workout session,
and you see that we updated state on the other side.
And we can probably end it, and now the state
of the workout also changed on the other side.
So to recap, we just saw how you can put some code
in your iPhone application, in order to put your watch
in a workout state, and at no point there was any user
intervention needed on the watch.
So, let's now talk about some basic practices we will like you
to follow whenever you are developing workout applications.
The first is that we want you to make sure
that your watch application is still functional whenever you
reach -- sorry, whenever you miss reach-ability
from your iPhone.
This is, for example, a user might expect
to start a running workout session, leave their house,
and go for a run, leave their phone behind.
In that situation, we do not want you to stop the workout.
So, the first thing that you need to do is
to keep your workout session active,
even when you lose connectivity with your iPhone.
Another interesting point in this scenario,
is that you can use HealthKit distance
because HealthKit is able to generate distance samples even
when you don't have a GPS available.
Also, we said that your user can start a workout
from either their iPhone or the Apple Watch.
I would advise if you give your user the choice,
on which device they want to start the workout from.
Other advice involves application display
If you do this, display workouts from all sources,
not only your own app.
We want you to show workouts generating
by other applications too.
If you're doing so, don't forget to observe deleted objects.
You do not want to keep displaying workouts
that were removed from HealthKit's database.
So, to finalize today, there are three things that we want you
to take from this presentation.
First, we learned about background running,
which is a great way of keeping your application updated
constantly, and having your user interface be responsive.
Second, you learned that you can contribute
to your activity rings by adding samples to your workout,
either on your watch, or your iPhone application.
And finally, third, we learned how you can start a workout
from either your watch or your iPhone.
So we would like you to go home or to your office,
take a look at your code, and apply what you learned today
to implement some great new features in your app.
For more information, you can go to this website
where you can see videos from this presentation.
We have some related sessions.
One from HealthKit and another one from Core Motion this year.
If you missed them, you can go online and watch them.
And here are also a few presentations
from previous years related to this topic.
This is all for today.
Thank you very much.
Enjoy the rest of your day.
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.