Getting information to your Watch app is crucial. Learn how to leverage NSURLSession to get your data from the Internet. Tap into the new WatchConnectivity framework for device to device communication and transferring of data. See real-world examples and learn best practices to understand when to use your WatchKit extension and when to leverage your iPhone app.
CHRIS JENSEN: Good morning.
Welcome to Introducing WatchConnectivity.
My name is Chris.
Today I'm joined by my coworker Alex,
who will join me on stage later.
We are excited to show you what we have been working
on for both watchOS 2 and iOS 9.
We think what we are going to talk about today is going
to help you make more responsive
and better user experiences for your Watch apps.
To do a brief recap of where we are coming from,
let's look at what the world looked like in watchOS 1.
Your iOS app and your WatchKit extension were both living
on the iPhone, and we were taking care of the communication
to the WatchKit app, and they could both share a data store.
In watchOS 2, we've moved the WatchKit extension
over to the Watch, and now your app is running natively
on the Watch.
This has a lot of benefits,
but it also means they now each have their own data store.
The obvious next question is going to be: How do we get data
over to the Apple Watch?
That's what we will discuss today.
So we are going to show you two main ways to deal
with this problem, of getting the data to the Watch.
There's the new WatchConnectivity framework,
which we are introducing in watchOS 2 and iOS 9.
And then there's the NSURLSession APIs available
These are still available to your WatchKit extension,
and it's now available native on watchOS 2.
We think the topics we are going to discuss today apply
to most Watch apps, and we think it's going
to apply to most of you.
This is exemplified by the amount of examples
that we will be using in our presentation today.
You can see there's a wide range here, and we hope that every one
of you will be able to identify with at least one of these.
So let's get started with discussing WatchConnectivity.
So this is the new framework we introduced
in watchOS 2 and iOS 9.
It's available in both platforms, and pretty much all
of the APIs are available in both sides.
There are couple of iPhone-specific APIs
that we will get into.
The first thing you want to do when you are starting
to adopt WatchConnectivity is you want
to go through the setup.
We recommend that you set this up very early
in your app's life cycle on both sides,
both on the WatchKit extension, running on the Watch
and in your iOS 9 apps.
You want to make sure you do this setup in a code path
that will be executed even
if you are being background launched.
So, don't put it inside, like, a view controller's View Did Load,
because when you're being launched in the background,
those won't get called.
So the first thing you want to do
in your iOS app is you will check to see
if the WCSession is supported.
You might have a universal iOS app.
Which means this code may be executing on an iPad,
where WatchConnectivity is not available.
So check this up front before you do any Watch-specific work
because we don't want you to waste a bunch of CPU doing work
that won't be used anywhere.
The next thing you want to do is create an instance
of our object, and you do that by calling Default Session.
And then you want to set a delegate on the session object,
and then finally you want to call Activate.
This will go and set up the WCSession object,
initialize all the properties, and once this call returns,
all the properties will be updated
with the correct initialization values.
And also at this point, any delegate callbacks,
any cued-up content can start coming in.
That's another reason why you want
to do this very early and always.
There might be content waiting to be delivered to your app.
So make sure you do these steps up front.
The next thing is you are going to want to do,
once you completed that step, is look at the session states.
This will inform your app about what the current relationship
between the iOS app and the Watch is.
So these properties are only available on the iPhone app.
It's informing the iOS app what its relationship
with the Watch is.
So you don't need to use this in your Watch app,
and they are mostly not available.
So for this example, we will use a news app.
Something that pulls down the most recent
And it's going to first go through the setup process
that we just discussed.
It will do this early in its life cycle.
Next, it will want to check, is this device paired with a Watch?
If it's not paired, then it's almost as if this is running
on an iPad, there's nothing more to do.
There's no one else to talk to.
So at that point you might
as well stop doing any Watch-specific work.
But the user will go out and buy a new Watch, and he will go
through the pairing process.
He will launch the Apple Watch app.
Work his way through the pairing,
setting these devices up.
And now, when your app launches,
you will get a delegate callback.
The session Watch state did change.
When you check the value of the paired property,
you will see it will return True,
because the devices are now paired.
So this is a trigger for you to go ahead
and check this next property, which is,
is your Watch app installed?
If it is not installed, then there's no one
to talk to, your work is done.
But -- and by default, the Watch app will be default --
but the user might choose to uninstall it for some reason.
In this case, the user will go ahead and reinstall it.
He will go back into the Apple Watch app and he will flip
that switch, and now if your Apple is running,
you will again get the delegate callback
and you can check this properties value,
and you would see that Watch App Installed is now True.
Now you do have someone to communicate with.
This should be a trigger for you
to start communicating with your Watch app.
It will need content that only you can provide for it.
Whenever the Watch App Installed switches to True,
there's this other property that's going
to be available, Watch Directory URL.
You will find that this,
whenever Watch App Installed is True,
Watch Directory URL will have a non-nil value.
It will be a path to a directory
that we create in your container.
Let's discuss this a little bit more in depth.
So the directory and its contents, its lifetime is tied
to the Watch App Installed property.
This means whenever Watch App Installed switches from True
to False, this directory and all of its contents goes away.
Whenever it switches back to True,
the directory will be present, but this time it will be empty.
We recommend you only use it for data relevant
to the specific instance of your Watch app.
What do I mean by instance?
Well, things like last queued item marker would be a good
thing to store there.
If the user uninstalls and reinstalls your app,
that Watch app is starting with a clean container.
Therefore, this directory will start clean, and you will need
to sync up where your app is communicating.
Other things you can put in is something like preferences.
When the user is running the iOS app for the first time,
you might like him to set up what he would
like his Watch app experience to be.
Maybe he doesn't want to show the full content
but the top ten news items for a particular topic
like international news or sports.
This would be a good place to store them.
Also if you are taking your full-sized assets
and generating Watch-specific assets,
you are compressing images, audio, video,
this would be a good place to store those while they are cued
for transfer, using the WatchConnectivity APIs
that we will discuss later.
So that's the Watch directory.
We suggest you store content in there,
because then we will clean it up, if the Watch goes away,
if he unpairs his watch, we will automatically clean
up this content, so you don't have to micromanage all of this.
The final property that's part
of the session state is Complication Enabled.
Currently, the user does not have the complication enabled,
but he will go in and edit his Watch face and he will enable it
and you will get the same delicate callback,
session or stated change.
And when you check this property, it will now be True.
Now you have set up your WatchConnectivity session.
You have figured out what the state of the world is,
what your relationship between your iOS app
and your Watch app is.
The next thing you will want
to do is start communicating information over to the Watch
or from the Watch to the iOS app.
And to do that, I will hand over to Alex, who will talk
about the communication APIs.
ALEXANDER LEDWITH: Thank you.
Okay. So like Chris said, you set up your session.
You have checked that devices are paired,
your Apple Watch app is installed.
Now let's start talking about how you can communicate
between these two devices.
We have a couple of different categories for communication.
First category is background transfers.
Background transfers are meant for content
that is not needed immediately on the receiving side.
Because the content is not needed immediately,
this means the system can do more intelligent things
when transferring that content.
In addition to background transfers, we are also going
to talk about interactive messaging.
Interactive messaging is meant for communicating
between two apps with live communication.
So both apps are up and running.
They are sending messages back and forth,
request response, that kind of thing.
Some examples of when you might want
to use interactive messaging.
Say you have a game where the user is using both apps
at the same time.
Or you are on your Apple Watch, and you need
to trigger something to happen on the iOS side.
Like you want to trigger the iOS device
to start tracking the user's location.
So let's dig into this first one, background transfers.
The first thing to talk
about for background transfers is the type
of content your apps have and how the user is going
to interact with these two devices.
So let's take that news app example again,
this news app has some content.
It's fetching some more content from the server,
and it determines some of this content could be useful
for your Watch.
Now, the user isn't using the Watch at this point in time.
So the content isn't needed immediately on the Watch side.
Rather, the iOS app, the news app, wants to just pick some
of that content and queue it up with the system,
and then allow the system to pick the right conditions
to transfer that content across.
The system will look at things like power, performance,
when the user is actually using the receiving side,
in this case the Apple Watch.
When conditions are right, that content will transfer across,
and it will wait on the receiving side,
in this case the Apple Watch,
until the user launches the receiving app.
When the receiving app is launched,
then that content will be delivered
and the app can update its state.
So this is what background transfers provide.
It allows you to queue up content.
The system is going to transfer the content for you.
This allows the sending side, the sending side app, to exit.
The system will handle the rest.
It allows the system to pick the opportune time to transfer
that content, and it allows the system to store the information
on the receiving side and wait for the receiving app to launch.
For a lot of the content your apps have,
we definitely recommend that you use background transfers.
The reason is most of that content will not be needed
immediately on the receiving side.
Rather, it will be needed
when the receiving app actually launches.
So let's get into some nuts and bolts.
We have three different types of background transfers.
The first type is the application context.
The application context represents a single set
of the most interesting information your app has
to offer to the other side.
So, for example, let's say on the iOS side you have an app
that tracks the user's location, and based on that location,
the app picks a restaurant in that location and wants
to recommend it to the user.
In addition to sharing restaurant on the iOS side,
you also want to show that restaurant
in the Apple Watch app.
So you could package up that suggestion
into the application context,
and that will get transferred across,
and then the next time the user launches the app
on the Apple Watch side, the content will be there,
that suggestion will be there to show.
Another example of when you might want
to use application context, say you have a social networking app
on the iOS side, it fetches a bunch of posts and determines
that there's a top 10 set of really interesting posts
that it wants to show on the Apple Watch side.
That way the user can look at the Apple Watch
and see interesting information right away.
You can also package up of those top 10 posts
into an application context, which will get sent across.
Now application context is the simplest way
of transferring content in the background,
but if you need something a little more complex,
or you need to queue up more than a single set
of information, we are offering two ways to do that.
The first way is user info transfer.
This allows you to transfer user info dictionaries,
in-memory content that you want to pack up.
An example of this is let's say you have a game
on the Apple Watch side.
The user progresses through levels,
and as the user progresses through levels,
you want to sync back that progression to the iOS app.
The iOS app will show some nice graphs
on how the user did in each level.
In addition to the user info transfer,
we are also offering file transfer.
This is very similar.
It allows you to queue up content, except in this case,
the content is a file.
One example that we are going to use in this presentation
for file transfer is let's say you have an iOS app
that allows the user to edit images
and after they edit those images,
the user can pick their favorites.
And those favorited images are the ones you want
to show in Apple Watch.
You can use file transfer to transfer
across those favorited images.
So they're available on Apple Watch
so the user can show them off
to their friends, that kind of thing.
So let's dig into these individually.
We will start with application context.
The example we will use
for application context is the social networking app example.
I mentioned before, this app on iOS fetches all the posts
from the social networking site
and then it picks the most interesting ones to send
over to the Watch app.
The first thing to talk
about with application context are these two properties.
The first property is Application Context.
It is the property that stores the latest content
on the sending side, and then on the receiving side,
there's Received Application Context,
which will store the latest received content
on the receiving side.
So let's say this iOS app has fetched a bunch of posts,
and it's packaged up the most interesting ones for the Watch.
It's going to want to call Update Application Context.
This method takes a dictionary, representing the latest,
most interesting state you want to send across.
This content, we take this content
after Update Application Context is called, and we push it
down into the Application Context property.
And this content will sit here,
and the system will determine a good time to transfer
that content across, maybe
when the user starts actually using their Watch.
Now, in the meantime, this iOS app could fetch more content
and determine that there's a newer set
of interesting information that it wants
to send over to the Watch.
In this case, it's going to want call Update Application
And then we're going to push that content
down into the Application Context property.
This is going to bump out the old relevant state and put
in the new relevant state because what we really care
about is the most interesting, latest set of data.
Now, this new content is going to sit here, again,
waiting for the system to pick a good time
to transfer that content across.
When the system does pick a good time,
that content will come across.
It will sit on the Apple Watch side.
And it will wait for the user
to launch the app, the Apple Watch app.
When that app is launched, we will deliver that content
to your WatchKit extension, the place where all
of your code is executing on the Apple Watch side.
So that's the flow of application context.
Now, let's take a look at some code.
The first thing you want to do is you want to package
up your context dictionary, representing the latest state
that you want to send across.
And then you will call Update Application Context
with that dictionary.
The last thing to mention about this code example is
that the call to Update Application Context is wrapped
in a Do Catch block, and the call is prepended by a Try.
This is new error handling in Swift.
Update Application Context can return an error.
And if an error is returned, the Catch block will be invoked,
and we strongly suggest that you handle your
So that's the sending side for application context.
Now, let's take a look at the receiving side.
On the receiving side,
the receivers will get this delegate callback,
Did Receive Application Context.
It's going to pass through the dictionary
that the sender packaged up.
And at this point, the receiver can take that content
and update its app state.
One thing to know about this delegate callback
and all delegate callbacks in our API is that they're returned
on a non-main serial queue.
If you need to do something on the main queue
because maybe you're updating some UI, you're going to need
to dispatch over to the main queue to do that updating
of your UI based on this content or something else.
So that's application context.
It's the most interesting relevant content
that your app has for the other side.
It does have overriding behavior,
and this is because you should treat the latest content
as the content that the receiving side cares about
and anything that's not latest isn't relevant anymore.
Application context takes a dictionary.
This dictionary takes property list types.
Property list types are basic object types such as numbers,
strings, basic collection types, dictionaries, arrays.
Apple has some great documentation online
if you want a refresher on property list types.
So we have some specific recommended use cases
for application context.
Application context works really well for many Apple Watch apps
because many Apple Watch apps show a subset
of the information the iOS app has.
So, if your app works like this, we suggest that you put
that subset of the information into the application context
and let it get sent across to the Apple Watch side.
In addition to those apps,
application context also works really well for glances.
Glances take the single most interesting piece
of data your apps have to offer.
So we suggest you put that piece of data
into an application context on the iOS side, so that it gets
across to the Watch side.
Then when the user swipes up on the clock face
to show your glance, that data will be available.
So moving on from application context, now we are going
to talk about user info transfer.
An example here that we are going to use is you have a game
on the Apple Watch side.
The user progresses through levels in this game,
and as the user passes one level, you are going
to sync back the progress that they made to the iOS side
so that the iOS app can show some nice graphs
on how the user did in that level.
The first thing to talk
about for user info transfer is the outstanding user info
This holds on to all the content that's waiting
to be transferred across.
The current state of the world
as the user progressed through two levels.
The progression is sitting
in the outstanding user transfer queue.
And currently the user is working on level three.
Once they finish level three, you are going to want to package
up that content and call Transfer User Info and pass
through a dictionary that represents their progress.
This will take that dictionary, and it will package it up
and it will put it into the outstanding user input
Now this content will wait here
until the system determines it's a good time to transfer
that content, based on power considerations or maybe
when the user starts using their phone.
The content will then transfer, and like the previous API,
we are going to wait until the app on the iOS side launches.
And when it does, we will deliver that content,
and now the iOS app can update those graphs
to show the progress the user made in their Apple Watch game.
So that's the flow for user info transfer.
Let's take a look at some code.
First thing you want to do is package
up your user info dictionary with all the content
that represents this current state
that you want to send across.
And then you want to call Transfer User Info
with that dictionary.
Transfer user info returns a user info transfer object.
This object contains the dictionary that's being sent
across, and it allows you to cancel this transfer
if the transfer is still in the outstanding queue.
In addition to this transfer object being returned,
we also offer a way to get all
of the outstanding user info transfers that are in the queue.
This returns an array, and you can iterate over the array,
look at all the contents,
and potentially cancel if you need to.
So that's the sending side for user info transfer.
Let's take a look at the receiving side.
On the receiving side, you will get this call,
Did Receive User Info Transfer.
Like application context and all the other delegate callbacks,
this is returned on a non-main serial queue.
Once you get that call, you can take that content,
that dictionary content, and you can update your app state.
That's user info transfer.
It takes user input dictionaries.
These dictionaries, like the application context dictionary,
take property list types.
It's good for in-memory content, like game progression.
And we give you access
to the outstanding user info transfers in the queue.
Next, let's talk about file transfer.
An example we will use for file transfer is this
The user can edit images on the iOS side,
and then they can select their favorites,
and those favorites are the ones we want to transfer
across to Apple Watch.
So the first thing to talk
about is the outstanding file transfer queue.
This is where all the file transfers will sit
when they are waiting to be sent across.
And then on the receiving side, the files will be put
into the Documents/Inbox folder while they are waiting
to be delivered to the receiving side app.
The state of the world is the user has favorited two pictures,
two images, that are sitting in the queue,
and they are working on a third.
Once they have completed that third and have selected it
as a favorite, you will want to call Transfer File.
And you will pass in a file URL pointing to the file
that you want to transfer, and we are offering a way
to transfer additional metadata in the form of a dictionary.
One example of when you might want to add some metadata is
if you want to group some of these files together
by putting an identifier in each metadata dictionary.
That way the receiving side can pull out that identifier,
group the incoming files.
So the user's favorited this image.
We called it transfer file.
Now we will take that packaged-up content,
and we will put it into the outstanding file transfer queue.
And it will wait here until the system determines a good time
to transfer the content.
When the system does determine a good time to transfer
that content, it will move that content across and it will wait
for the receiving side to launch and take care of that content.
One thing to note about files,
files can be a little bit larger.
And the larger the file, the longer it's going
to take to transfer across.
Potentially you might hit power conditions,
performance conditions while those are transferring.
Just be aware if you have large files that are trying
to transfer across, they may take longer
than the transferring in some of the other APIs.
Now the receiver will launch,
and we will deliver these images.
And now the Apple Watch app can show those images off.
So that's the flow of file transfer.
Now let's take a look at the code.
First thing you want to do is you want to get your URL
to the file that you want to transfer.
Then you want to package up your metadata and finally,
you want to call Transfer File, passing through that URL
and that metadata dictionary.
This returns a file transfer object,
the file transfer object contains the URL,
the metadata dictionary, and also gives you the ability
to cancel any file transfers that are outstanding.
Just like user info transfer, we offer you the ability
to get the array back of all the outstanding file transfers.
You can iterate over this array, check the contents,
and cancel if need be.
So that's the sending side for file transfer.
Now let's take a look at the receiving side.
On the receiving side, you are going
to get this delegate callback, Did Receive File.
There's a few things to mention about this delegate callback
that are slightly different than the previous two.
First, you are going
to be getting this WCSession file object.
This object just contains the file URL and the metadata.
The second thing to talk about with this callback is
that the file is now in the Documents/Inbox folder
of your app's container.
But to take control of this file, you need to move that file
out of the Documents/Inbox folder
into a more permanent location.
So the main reason you need to move this file is
that the Documents/Inbox folder will be cleaned
up after this delegate returns.
This means the file will be deleted out of there along
with any additional content.
So it's really important that you move this file
into a more permanent location inside this delegate callback.
One thing to keep in mind if you are dispatching
to a different queue because this is returned
on a non-main serial queue, you will need
to move the file before you do that dispatching,
if that dispatching is async.
So that's file transfer.
It's very similar to user info transfer, except it allows you
to transfer files or queue up files.
We do offer the ability
to access the outstanding files in the queue.
And we provide the ability to transfer additional metadata.
We suggest you keep this metadata small,
and this metadata dictionary,
like the other dictionaries we talked about,
takes property list types.
So those are the three background transfer modes.
Use these if the receiver does not need the
If, however, you need to send messages back and forth
in a live fashion, you can use interactive messaging.
And interactive messaging is meant
for that live communication, both apps are up and running
and they are sending messages back and forth.
Like I mentioned before, some examples
of when you might want to do this.
Let's say you have a game where both UIs are up
and you want the user to be interacting with both.
Or if you are on the Apple Watch side and you need
to trigger the iOS app to do something,
like start tracking the user's location.
Now, there are certain conditions that need to be met
for interactive messaging to be used.
So let's talk about those conditions.
It all relates to this idea
that we are introducing called reachability.
And what reachability means is
that the other app is available to receive content.
It is required that the other app is available,
the other app is reachable, to use interactive messaging.
And the way that you check
that the other side is reachable is we have this property
on the default session, Reachable, that you can look at.
Now, the conditions
for reachability are slightly different depending
on what slide you are on, whether your code is executing
in your iOS app or it's executing
in the WatchKit extension.
So let's look at those individually.
We will start on the iPhone side.
The first condition that needs to be met for Reachable
to be True is that the devices needs to be connected.
This is connected over Bluetooth or over Wi-Fi,
but if the user leaves their Watch at home, takes their phone
with them to work, the devices won't be connected
and interactive messaging is not going to work in this case.
The second condition that needs to be met for Reachable
to be True on the iOS side is
that the Watch app must be foreground.
This means the user must be interacting with their Watch app
for interactive messaging to work from the iOS side.
Once these two conditions are true,
the Reachable property will be True in your iOS app.
So that's the iPhone side.
Now let's talk about the Apple Watch side.
The first condition for Reachable to be True
in your WatchKit extension is
that once again devices must be connected.
This means that if the user goes for a run and leaves their phone
at home and takes their Watch with them,
Reachable will not be True.
The devices will not be connected.
The second condition is that the WatchKit extension needs
to be foreground.
We mentioned the WatchKit extension here being foreground
because there are certain cases
where the WatchKit extension can run in the background.
They mainly relate to complications, and we will talk
about this a little later in the talk.
For now, when the user is using your app,
your WatchKit extension is going to be running
and your WatchKit extension will be foreground,
which means you can use interactive messaging
and the Reachable property will be True.
One other thing to note about this diagram.
We are not saying that the iOS app is running.
The iOS app has to be running to respond to messages coming in,
to send its own messages.
So how do we get into a state where the iOS app running
in addition to the WatchKit extension?
Well, for this direction only, sending messages from the Watch
to the phone or allowing the iOS app to be launched
in the background upon receiving a message.
So let's take this example.
You have a run tracker app and it needs to send a message
over to the iPhone side to talk to CoreLocation
to start tracking the user's location.
So this app is going to package up a message
that tells its iOS app to start using CoreLocation,
and it's going to send that message across.
When the system receives this message, we are going
to launch the iOS app in the background
and deliver that message.
Now, both apps are running, and now they can do communication.
This app in this example can start tracking the
So that's kind of flow of interactive messaging.
Kind of how it relates
to reachability, when you can use it.
Now let's get into the nuts and bolts
of how you use it in your code.
We are offering two different types of messages.
The first type takes a dictionary
and you use this call, Send Message,
which takes that dictionary,
plus a reply handler and an error handler.
This dictionary, like the dictionaries we talked
about before, takes property list types.
In addition to dictionaries,
we are also introducing a way to send data.
You can send data by calling Send Message Data.
This takes that data plus that same reply handler
and that same error handler.
For sending data, we suggest you use this if you have custom data
that you're storing your information in
or if you have your own serialization format.
If you are using your own serialization format,
we strongly suggest you use one that's quick and compact.
This way the user experience is faster
because the content is transferring faster.
One thing I want to point out about these calls is replying.
You probably noticed the previous two calls have
This handler is optional.
However, we do recommend in most cases you use it.
The reason is that this allows the receiver
to confirm the incoming message.
The receiver can confirm that it received the message.
The message contained the right content, and it was able
to process that content.
And then this way the sending side knows that it doesn't have
to send anything else.
It doesn't have to send anything new
because it sent the wrong stuff.
The other part to talk about for the replying is what happens
on the receiving side.
What happens if the sender says, "I want to reply, so I'm going
to supply a reply handler," versus if the sender says,
"I don't want to reply, I'm not going
to supply a reply handler."
In these cases, we have separate delegate callbacks the receiver
is going to get, depending on whether
or not it should supply a reply.
So let's talk about those delegate callbacks.
In the first case, the sender says, "I do need a reply,
I'm giving the system a reply handler."
This means that the receiving side will get this delegate
callback, Did Receive Message, it has a Reply block
that you can call after the receiver has received the
message and processed it, and the receiver can then determine
if it wants to send back some content
or maybe send back an error if the message is wrong.
Now, on the other hand,
if the sender doesn't supply a reply handler,
the receiver is going
to get this delegate callback, Did Receive Message.
It doesn't have a Reply block.
The receiver can process the incoming content
and they are done.
The last thing to note
about these two delegate callbacks is they pass a
This means that the sender used the send message,
sending on the sending side, to send a dictionary.
If instead the sender used send message data to send data,
there is analogous callbacks on the receiving side
that pass through data.
So now that we kind of have a feel for interactive messaging,
let's put it all together and code for the sending side.
The first thing you want to do is you want
to check reachability, make sure the other side is
Then if Reachable is True, then you can package up your message.
And once you have your message,
you can call Send Message with that dictionary.
We expect a reply.
So we will supply the reply handler,
and we want to handle our errors,
so we will implement an error handler.
So those are the different ways
to transfer content using WatchConnectivity.
So let's sum up what we've talked
about for WatchConnectivity.
The first thing you want to do is you want
to set up your session.
To do this, you set your delegate, and you call Activate.
You want to do this early in the lifetime of the app
so the app has the ability to start receiving content
and the ability to start checking properties.
To check those properties, you look at the session state.
And once everything is okay,
once you know there's a paired Watch,
once you know your Apple Watch app is installed,
you can start communicating.
The first type of communication is background transfers.
We offer three types.
The first type is application context.
This is for the single set of really interesting information
that your app has for the other side.
Or if you need to queue up content,
you can use user info transfer or file transfer.
In addition to background transfers,
you can use interactive messaging
for live communication.
So that's WatchConnectivity.
It allows device-to-device communication between your apps.
And we are excited to see what you do with this API
to get content back and forth
and provide better user experiences.
Next, we're going to talk about NSURLSession briefly.
So what is NSURLSession?
It's an existing foundation class.
It allows you to make HTTP requests
to your servers to fetch content.
It's available in watchOS 2, and we strongly suggest you use it
if your servers have content that needs to be fetched.
And it takes advantage of the Tetherless Wi-Fi feature.
The Tetherless Wi-Fi feature allows Apple Watch to connect
to known Wi-Fi networks when the phone is not around.
If the Apple Watch does connect to known Wi-Fi networks,
you can use NSURLSession to go over that Wi-Fi to connect
to your servers and fetch content.
So what do you want to use NSURLSession?
You want to use it any time your server has new content.
This is very similar to how you might be doing stuff
in your iOS apps.
We do suggest, however, that you tailor the content that's being
delivered to Apple Watch based on how Apple Watch works.
So if you have images on your server,
we suggest you scale those images for the screen size
of Apple Watch, or if you are a news app and you are only going
to show some of article, maybe just the text, on Apple Watch,
we suggest you only fetch the parts you need.
So that's a very brief introduction to NSURLSession.
There's a great WWDC session on this API as well
as great online resources.
So we definitely suggest you check those out.
Now, the last thing we want to talk
about for NSURLSession is using NSURLSession
So once again, we have the example of our news app.
This news app has fetched a bunch of content
from its server, and it knows
that the Apple Watch app probably will have
to fetch this same content the next time the user launches the
Apple Watch app.
Instead of making the Apple Watch app refetch that content,
we will use application context to transfer across the content
from the iOS side to the Watch side.
That content is going to come in, and it will be delivered
to the Apple Watch app the next time it launches.
And now the Apple Watch app has the ability
to show the same content that was seen on the iOS side,
and it provides a more cohesive experience.
Now the next time the user launched the Apple Watch app
could be a couple of hours later,
which means the server has even newer content
that might want to be fetched.
So we suggest that in addition to taking
in the application context that was sent over,
you use an HTTP request with NSURLSession
to fetch the absolute latest content from your server.
But this way, while the user is waiting for that content
to come down, they will see the same content they saw
in the iOS side and they will have a better experience.
So that's NSURLSession, NSURLSession
Now, we want to take these two APIs and we want to show you how
to use them to get data to your complication.
And to do so, I will bring Chris back
up to the stage to talk about this.
CHRIS JENSEN: Thank you, Alex.
That's some cool stuff, right?
I think it's going to be great to see what you guys end
up doing with the WatchConnectivity APIs
and the NSURLSession APIs.
Now let's discuss complications.
But before we dig in too deep,
let's make sure we are all on the same page.
These are three Watch faces,
three clock faces on the Apple Watch.
If you remove the timepiece,
the remaining pieces are complications.
They provide small snippets
of information every time the user looks at their clock face.
And this will allow them to get sort of the most important piece
of information really quickly.
So when you are implementing your complication,
there's two primary tasks that you will have to solve.
You will have to figure out how to update the clock face,
and the second one is you need to get the content to use
to update the clock face.
So let's discuss how you would update the clock face briefly.
This is covered in depth at other sessions.
For this example, we will use a weather app
that has a moon phase complication.
The moon phase complication doesn't need any external data.
It already has all the information it needs
because it just needs the date and time.
So all it needs to concern itself with is how
to update the clock face.
To do that, it's going to use the new ClockKit API,
the ClockKit framework introduced in watchOS 2.
The way the flow works is we're going
to launch our WatchKit extension in the background.
When this happens, you are going to want to get an instance
of CLK complications server.
You call Shared Instance to do that.
And you will call Extend Timeline For Complication,
and you pass in the complication that you are updating.
The next thing that will happen, that will trigger our process
with ClockKit and they will start asking you a couple
They will ask for the current timeline entry.
This is the one that's going to be shown right now.
They will ask for previous timeline entries,
future timeline entries, and finally, they are going to ask
for a suggestion of when you think this data will be stale.
This is a suggestion to the system so that we can know
when you think that you need to get launched again.
So you can update your timeline further.
That was a quick summary of updating the clock face.
You would use the ClockKit framework to do so.
You will be able to provide content
for past, present, and future.
Your WatchKit extension will get launched in the background
to do these updates, and you will be given a chance
to specify when the content provided is going to be stale.
One thing to keep in mind is that all the work
that your WatchKit extension is doing on behalf
of updating the complication is budgeted, so you want to try
to keep this as fast and efficient as possible
so that you can keep getting launched throughout the day
to update your complication.
As I mentioned, there's a great talk dedicated to this topic,
Creating Complications with ClockKit.
We want you to check that out if you haven't done so.
The next you will have to deal with is how
to get content to your complication.
There's a very special instance, which is the initial activation.
The first time the user goes into his clock face,
he's going to go in and edit it and then he's going
to enable your complication; in this case,
the news app complication.
At this point in time,
that complication very likely has very little or no data
to populate its timeline.
So it has a large need for a lot of content.
So what's going to happen is we are immediately going
to launch your WatchKit extension in the background.
And now you have a couple of different ways of getting
that content so you can initialize that timeline.
You could use NSURLSession to communicate with your servers
to get that content, or you could choose
to use WatchConnectivity.
If you are going to use WatchConnectivity
in this very special circumstance,
and the devices are connected, you will find
that Reachable is True.
This is what Alex was referring to earlier,
where this property might be True
in certain special circumstances.
This is one of those.
What you are going to be able to do
in this case is you will be able to call Send Message,
which will send a message across to the iPhone.
And we will wake up the weather app in the background,
and at this point, the weather app on the iOS side can use any
of the WatchConnectivity APIs to communicate the information back
to populate that timeline.
So in summary, when you are going
through the initial activation,
your WatchKit extension will get launched in the background.
You can use NSURLSession or,
because this is a very special circumstance, you will be able
to use the WatchConnectivity APIs to wake up the iOS app
because Reachable is True.
We suggest you use this to populate as much
of the ClockKit timeline as possible
because it's starting with nothing.
The next issue is how to stay current.
Your timeline is now populated,
and now future updates will be happening.
How do you keep updating your complication?
So there's a couple of different ways that you could use
to update your complication.
You could get content pushed to your complication.
This makes sense if you have an external source
such as a web server that knows specific times
when there is new content and it's not a regular cadence.
What you are going to want to do then is have the content push
from the clouds to the iPhone, and then it gets relayed
over to the Apple Watch.
An example of where we think this makes sense is something
like a sports app, where the complication is showing
Most of the time, those scores are going to be happening
in a short period of time during the day,
and it will be very rapid updates.
So then we think it makes more sense
to use the pushed approach.
The other one is what we're calling requested
This is more for when you know there's a regular cadence
where you can keep updating your complication.
And then you could use something like NSURLSession
to go directly to the cloud.
Something like a surfing app with a tide complications
that shows what the tidal patterns will be so you know
when to go out surfing.
So let's take a look at this case first.
In this case, you will want to use NSURLSession and ClockKit
to update the complication.
As you can see in the corner of clock face,
the surfing complication is already enabled.
The flow is going to go a little bit like this,
where the WatchKit extension gets launched in the background.
You're going to want to generate an NSURLSession request
and you send that up to your servers to get content.
The server will produce a response
and it will get delivered back down to the WatchKit extension.
Now you want to turn around and update ClockKit.
So you will request them to extend your timeline.
They will start asking you these questions, and you're going
to give them the timeline updates, both past, present,
and current, and finally, you are going to suggest a time
for when you should be launched again.
And the last thing that will happen is when you provide
that time for when you next should be launched,
that's a hint to the system that your work is done,
and your WatchKit extension will get killed.
So now, let's pretend that some time passes,
and the system has decided based upon your hint
and system conditions that now is a good time
to relaunch your complication.
Again, you are going to get launched in the background.
You are going to produce a request, using NSURLSession.
You are going to send it up to the servers.
The servers are going to produce a response, and you are going
to turn around and update your complication using ClockKit.
So in summary, and a couple of tips is that we suggest
that you use NSURLSession background session if possible.
This is because the NSURLSession request might not complete
until the next time the extension runs.
Using the background session enables it
to deliver the content the next time you run.
The requested time that you are providing is just a suggestion
to the system.
It's not a guarantee.
We'll try to get you close to that time, but conditions apply
and it may not always be exact.
We suggest that you keep the runtime as short as possible,
and you will use ClockKit to update the clock face.
You want to keep runtime as short as possible and make sure
that you make your next requested update time as far
out as possible because these are budgeted and you don't want
to run out of budget before the day is over.
The other approach to getting the content,
which was in our example of the sports app,
was to get the content pushed.
We will look at this in a couple of stages
because it uses two very distinct processes.
The first one is you are going to use PushKit
to get the content from the cloud to the iPhone.
The second part is using WatchConnectivity to get
that content from the iPhone across to your Apple Watch.
So let's look at those separately.
So part number one is where you are using PushKit
to get the content to your iPhone.
We have updated the PushKit framework to add support
for these complication pushes.
The way you use it is you create an instance of PKPushRegistry.
Next, you will want to set yourself as a delegate
so that you are ready to receive callbacks.
And finally, you will set the decide push types and pass
in the new PK push type complication
that that was added in iOS 9.
Once this is done, you will get a delegate callback
with a new Push token, which you're going to want to upload
to your servers, which is going to enable your servers
to send pushes to this device.
Finally, when the server does send the push,
you will get the Did Receive Incoming Push
With Payload callback.
And this when you turn around
and use the WatchConnectivity APIs
to send the content over to the iPhone.
So for the second part, this is where you are going
to use WatchConnectivity to get the content
across to the Apple Watch app now
that you received it in your iOS app.
The first thing you are going to want
to use is the transfer user info API that Alex discussed earlier.
This will allow you to queue up timeline entries
for both the past and the future that your iOS --
sorry, your Watch complication might need.
Once you have queued up all the timeline entries,
the last thing you want to do before you are done
with your work is called a special API.
It's also part of WatchConnectivity.
It's called transfer current complication user info.
This is a special version of the transfer user info,
and at any point in time,
there can only be one current complication user info.
If you call this twice, only the most recent call is the one
that is tagged as the current complication user info.
When you call this, this is a hint to the system
that the work is done, and on the receiving side all
of these callbacks will produce this delegate callback,
Did Receive User Info.
So let's look at what this all would look
like from a full flow.
So the user has launched a sports app
for the very first time.
Your app early in its life cycle will want to set
up the PK push registry and set the desired types.
This will register this push --
this device with the Apple push servers.
So that will get pushed up to the Apple servers.
It will turn around and produce a Push token, and you will get
that delegate callback in your iOS app.
You will want to take that token and upload it to your servers,
enabling your servers to send pushes
to this device in the future.
At that point, the initial setup of the PushKit is done
and your app can go away.
Let's say the game starts, and the server decided it needs
to update the complication.
It will send a push down to your device.
That will get received on the device, and we will wake
up the sports app in the background and deliver the push.
That was that other delegate callback.
At this point, you are going to want to look at the data
in the push payload and figure out what needs to get sent
across using WatchConnectivity.
You will call Transfer User Info to queue
up the timeline entries, both past and future,
and that will go into the outstanding user info
And then you call the special transfer current complication
user info with the one that's most important,
and that's the one that should be shown
on the Watch face right now.
That will also go into the outstanding user info transfers
queue, but it will skip to the front
because it's the most important one.
And because this is considered urgent, we will try to get
that across to the Apple Watch right away,
and wake up the WatchKit extension in the background
and deliver that current complication user info.
Given conditions, some of other content might also transfer
at this point in time and you will get those other timeline
entries, but at least the most important one made it across.
Finally, you want to use ClockKit
to update your complication.
So there we go.
You have updated your complication using PushKit.
We have added the new PK push type complication to enable you
to very quickly update your complication using information
that's on your servers.
There's a couple of restrictions to be able
to use these push types.
The complication must be active on the current clock face,
otherwise these pushes will not be delivered,
and there will be a limited number of pushes per day,
so use these sparingly.
Roughly one to two per hour on average,
but the sports app may use them all in a short period of time.
You would use transfer user info to queue
up your timeline entries.
And finally, you would use transfer current complication
user info to queue up the current
or present timeline entry.
Finally, you would use ClockKit to update the clock face.
Keep in mind that a lot of these things are budgeted.
Any work you do on behalf of complication update,
both on the iOS and on the WatchKit side,
counts against this budget.
So we recommend that any information you need
to update your complication is included in that push.
The complication push type has a 4 K payload, which is larger
than the standard, so that should enable you to put most
of the content you needed.
If you receive one of these pushes and you turn
around in your iOS app and do an NSURLSession request,
you will run out of budget much faster.
So make sure you include all the content you need in the pushes.
That brings us to the end of our session.
Briefly going to discuss what we talked about today.
We went through the WatchConnectivity framework
We look forward to seeing what you guys can do with these APIs.
We briefly discussed NSURLSession and its use.
There's other sessions that go more in depth on what
and how to use NSURLSession.
And finally, we discussed how to get data to your complications,
which is a more advanced topic.
There's a lot of other great resources to check out.
We have some great sample code,
and we have our evangelist that's ready
to answer any of your questions.
As far as other related sessions,
we especially suggest you check out Creating Complications
with ClockKit and Networking with NSURLSession,
as those are closely related to the content we discussed today.
Thank you very much.
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.