Transcript
[ Music ]
[ Applause ]
>> Hello, everyone.
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
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.
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
their device.
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.
[ Applause ]
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
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
workout configuration.
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
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.
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.
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
to HealthKit.
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,
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.
[ Applause ]
>> Thank you Dash.
Good morning.
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,
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.
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
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.
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
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.
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.
That means they are
not running anymore.
And we will be able to
detect whenever they start
running again.
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,
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
startAccumulating Data.
So let's take a look
at this function.
What we want to do is to update
those two labels that we saw
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
the presentation.
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,
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
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
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
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.
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.
to invite my colleague
Dash again on stage.
[ Applause ]
>> Hello again.
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.
[ Applause ]
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
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
workout session.
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.
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
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.
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
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.
[ Applause ]
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.
[ Applause ]
>> Thank you, Dash.
So you've been developing great
applications for your iPhone.
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.
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
workoutConfiguration object.
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
with workoutConfiguration,
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.
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
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.
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
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
with workoutConfiguration.
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
changes state.
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.
[ Applause ]
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
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,
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
historic workouts.
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.
[ Applause ]