watchOS 2 provides a new architecture that runs your WatchKit extension directly on Apple Watch. Take an in-depth look at how this new architecture works. Learn how to migrate existing WatchKit apps to watchOS 2, how to support both versions of watchOS, and hear about updates to Glances and Notifications.
ANDREW PLATZER: Good morning, everyone,
and welcome to WatchKit in Depth Part 1,
the first of two sessions to explore a bit more
about the changes in WatchKit.
My name is Andrew Platzer and along
with Forest Hill we will be covering some topics today
hopefully of interest to you.
I'm going to be covering three sections, architecture,
the basic layout of how a watch extension works inside a
I will talk about where resources and data live
because it is a two-part system,
and so it may be a bit confusing to start with.
For those who have already worked on watchOS 1,
a WatchKit extension, a watch app, I will talk a bit
about migrating over, what's changed, what's the same,
and then Forest will carry on and talk a bit more about some
of the new API and the new classes in WatchKit.
So your Watch app has three parts.
It's got an iOS application,
and that is what you would get installed on the phone,
as well as that, you provide a WatchKit extension,
this is the code you write, and then a watch OS application
which contains resources and interface description.
You have your phone and you download your app,
and what we have done is added a new bundle of data,
bundle of files that get along with, install along with it,
and that's the Watch app,
that contains your interface description
and maybe some resources, and then your WatchKit extension
which contains code and additional resources.
So when you pair it with your watch, we copy over all
of that information, and it appears on the Home screen
as a full application.
Of course, a copy is still left on the phone for later
in case it needs to be reinstalled.
So I want to talk about the two parts
that you are going to be providing.
One is the interface and the other is the actual code
and the extension.
When you create a new WatchKit App,
you can see there are actually two separate targets,
two separate components, the app with the interface storyboard
and your code, in this case in Swift, and you have
up to four different things you can add code for.
So for the storyboard, this is the interface part of it,
you can edit in IB just like you would an iOS application,
and we provide a reasonably rich set of interface elements,
labels, images, et cetera.
This is all in watchOS 1 and we have added a couple of new ones
in watchOS 2, the thicker view,
which will give you a lot more rich interface,
and the movie view.
So, for example, here are three standard possible controllers
with all of the controls you can see,
and these are created in interface builder.
We also have custom interfaces for specific functions,
one is Glances, and it's got a more specific layout
and the other two are for notifications.
One is for static, one is for more dynamic information
which you provide at run time.
So as I said, there are four roles for your extension.
There is an application role,
so when your application is launched from the Home screen,
we call your extension.
It's also used for the single page glance that appears
from the clock, notifications when you receive one,
and now complications.
And for each of these, there is an associated controller,
for the Glances and the regular application,
there are WKInterfaceController.
There is the specific sub class called WK user notification
controller which you should use for notifications,
and there is a new data source object CLK complication
I won't talk anymore about the complications.
There is a session later today that will go
into great detail about this.
So your WKInterfaceController is your main connection
to your interface.
The main thing it does is it provides automatic creation
of interface properties so you tag an interface element
in your interface design and say this is like, for example,
my label, and then we create an associated object
on the controller and we connect it up automatically for you.
The controller also supports menu handling.
You can customize menus or have static ones.
We provide navigation, push and so on, or paging,
modal presentation of controllers
and alerts, and action sheets.
One other thing we do provide is a number of system UI sheets,
text input, video play back, audio recording.
So, for example, here is a very simple interface
It has one outlet, app image and we have loaded up in IB
and when we run the application we see it pulls the image
and displays it on the screen.
So I want to talk a little bit about the location of stuff,
where your resources live, where you can pull your data from.
Because there are two parts to this watch app,
there is the watch app itself and the WatchKit extension,
there are two places where data is stored,
there's the WatchApp bundle and the WatchKit extension bundle,
and you have got to be sure you remember where it is.
For example, here I have created another project,
it has an interface storyboard as before
and also an application image.png
and the localized string file
and the extension itself also has the same kind of thing.
It has another .png file and a localizable string.
So now if we do the obvious, which would be create a couple
of outlets, wire them up using IB outlet to indicate
that these are the properties, and call set image, well,
we don't get an extension image.
The reason for that is that when you call set image named
on a WKInterfaceImage, it doesn't look
up in the applications bundle,
but the extension image doesn't live in the applications bundle.
So instead, what you need to do is directly fetch it
in the code that's running in that particular bundle.
So in the extension code, you call UI image 'image named,
and it will pull the image locally since it knows how
to search inside its own bundle.
Then you send that across.
You call set imagine instead of set image named so it will pass
over the image and both will appear in your application.
So now you want to store some data.
You don't want just pull some static images.
You have a much more dynamic application,
so there are two folders that are of interest.
One is the documents folder,
this is where you would store more persistent information.
It's not purgeable.
That means it hangs around between reboots, et cetera,
but one thing to note, it is not restored, so you may have
to check for that if the watch was erased
or you go to a new watch.
There is also a caches folder.
This one is purgeable, so if the system decides it needs more
storage for music or pictures or other apps,
it will remove those images,
so you should consider those may go away at any time.
And so here is a quick example of where to find it.
In this case, the main call here is the document directory class
file manager for URLs for directory.
It will ask for the first one and that's the URL.
So we can create a URL including our file name
and write some data to it.
Now, media presents another interesting problem
because the application is in charge of playing the media,
and it's also in charge of recording it audio somewhere.
So when you, your extension requests to play a movie
or play audio or record audio,
we send that off to the application.
On the other hand, the extension is in charge of getting
that media, downloading it from the internet or generating it
or whatever, and it's also in charge
of getting the recorded audio files that you may have set up
and sending them out to your server.
So what you need to do is set
up what's called a shared container.
And that basically lets both processes, the application
and the extension have a common place to access.
Because for security reasons, normally you can't access
from one process into another's storage area.
And you enable this index code.
You use something called 'app groups' for both the extension
and the application you give a unique identifier
and that's your application group.
And so the only real thing here you need to worry
about is there is a single function, again,
the file manager, you can ask container URL
for security application group identifier and you will pass
in the group identifier that you created
and that will give you URL to a shared storage area.
So from there, you can save files that the app can read
from the extension or pull files that the app wrote
into the extension
and an example here we have a present audio recording
controller and that takes the URL from the shared container,
so it will record the audio to that file.
So now, I want to talk about getting the data to the watch.
There are two ways of doing that,
one is NSURLSession, whichs in foundation.
And the other is a new framework called watch connectivity.
So the NSURLSession is the one you use a lot to get stuff
from the internet, if you have got a chat app or something
like that, you will want to talk to your server,
it gives you direct access to the internet using HTTP
and HTTPS and there are several ways of configuring it.
And it allows for backgrounds and downloads.
The reason for that is your extension is often not running,
your watch screen is turned off, your extension is sleeping,
your extension may not even be running for awhile
that it takes to download the data.
One thing to note is once we tell you the data is there,
once the file is completely downloaded,
you need to grab it right away,
because otherwise it will be removed from a temporary cache.
So here is some code, a couple of pages,
a simple downloader class.
The first thing we do is cut an NSURLSession, we do it lazily
in case we don't need to ever call it.
And the main call here is to create the session.
And there's really two lines.
One is you configure it for the background,
so you want to say here is a background session,
and we want to pass in an ID, and I'll talk about that
in a moment, and we create the URL session
with that configuration
and we make the downloader class itself the instance
after a delegate so we get notification
when the file comes in.
Then to start the URL download, we ask for a new task
and tell it to go, and it will send off the request
and start the download.
So as I said, often your extension is shut down
or not awake while that's happening.
In the case where it's shut down, you will want to reconnect
to all of those download tasks you have set up.
So what you will set up is, for example,
a function here called restart that you might call
from your WK extension, and Forest will talk about that,
at start up to restart the download
so that you know they are coming.
Actually they will be going, but you won't know
that they have finished.
And so here is the actual delegate method.
This is the one you are wired up to the NSURLSession,
and it's called when the file finishes downloading,
and as I said, we need to copy the file immediately
so it doesn't go away, so the system doesn't remove it.
In this case, we will get the caches directory
because maybe we will need it a short while.
We will generate a URL, and we will call the file manager
to copy that from the original URL that passed in,
the location URL to the cache's directory URL.
So we have a copy of it and we will keep track of it for later
so we can access whatever the data is you downloaded.
There is also the WatchKit connectivity framework.
It actually exists on both sides.
If you share data between them so, for example, you could set
up a dictionary that could share
between the watch and the iPhone.
It lets you transfer files over, again, the background,
and it lets you send direct requests from the watch
to the phone app your parents,
your parent iPhone, parent application.
And there is a session on that tomorrow,
and I suggest you definitely listen to it because it is new
and does exist on both the watch and the iPhone.
So just a few slides on migration, for those of you
who have started a watchOS 1 app,
you have probably run into this.
The WatchKit extension
for watchOS 1 is something you have created already,
there is a target in your project,
but it uses the iOS platform in SDK.
So it lives on the iPhone rather than on the watch.
Because of that, it lets you share a framework on the phone,
so you might have some code that's common
to both the extensions, for example,
fetching your information from the network, and you will have
that same code being run by both the iPhone application
and the watch application.
Because you have no direct storage access to the watch,
we gave you a way of caching images
of basically saying here is an image and here is a name
and later on when I say 'said image named,
we will have already downloaded that asset, those resources
to the watch, and it will be much faster.
So we gave you a way of directly talking to the application.
Obviously this is from the phone
to the phone process so it's very fast.
With watchOS 2 we have added a new SDK.
It's completely separate,
similar to the iPhone and OS 10 SDKs.
It does give you a subset of available iOS frameworks,
so you won't get the complete set of functionality as you do
on the phone, but you will get a lot.
You can, in your project, include a framework just
like you did on your iPhone watchOS 1 app, but, of course,
this framework is downloaded with the watch application,
watch extension, and so you don't get to share the code
in one device, but it does let you still separate
out your network access code into a separate framework
that the watch can use.
Now, of course, the watch, for example, for watch framework
that you provide, for example, might use NSURLSession
to access information.
So if you have done a watchOS 1 application,
you have actually already actually got a lot ready
for watchOS 2.
It's got the same API with some changes and additions.
But you should be able to compile a lot of it
without any changes at all and copy resources over,
so if you have images in your watchOS 1 extension you could
add them to the target of the watchOS 2 extension
and have them copied to the watch.
But you do want to make sure they are sized appropriately
for the watch.
There are a couple of new things.
The main thing, of course, is that your watch app is running
on your watch, and so the extension is running,
and that means UI responsiveness is much better.
You tab a button, and it immediately responds.
Of course, you have also got independent operation now
and you don't have to worry about the phone being nearby,
you don't need to worry
about the phone being connected or on the network.
We added a couple of UI elements as well
as some new system UI sheets and those will be talked about later
in the session and in other sessions.
We have added animation, so now you can animate the transitions
between changing, for example, the size of a graph or a graphic
or a size or something like that or the opacity
of a string, you can animate that.
There is a session for that tomorrow.
So I suggest you take a look at that one as well.
So for controllers, the API is pretty much the same.
So you have got the same interface controller
and the same, you will use the glance,
nothing has changed there and the same for the notification,
you don't need to make any changes there.
There are a couple of APIs which are no longer there,
image caching and open parent, those have been replaced
with direct images and watch connectivity.
Two new things are the extension delegate which Forest will talk
about in a bit, and the complication data source
which is used to provide the images and text
for complications display on the watch face.
For those having existing Xcode projects,
you can add a new target.
You can have the watchOS 1 there,
you can say give me a watchOS 2 and add files in,
mark files as part of the same target, so on,
add the frameworks to be compiled
and loaded on the watch.
If you want, you can start from Xcode with a whole new project,
and it will automatically create the iOS and the watchOS 2 app
so you can start it filling in from there.
There was a session yesterday, I suggest you take a look
at the videos that detail this procedure much better.
And that's it for me.
So now I will hand it over to Forest who will go
into more detail about the new classes
and changes to the existing API.
FOREST HILL: My name is Forest,
I'm an engineer on WatchKit.
I would like to talk to you about the APIs we have added
in WatchKit for watchOS 2.
First I'd like to talk about WK extension delegate.
On iOS we have UI Application Delegate.
Among other things, this serves
to help you track your app's life cycle, this includes things
like your did launch, your did become active.
And your will resign active.
We have added WK extension delegate
to track your application's lifecycle.
First up, I will start
with application did finish launching.
This will be called once
when the application has finishes launching
from when your extension hasn't been run at all.
This is a great place to perform initialization steps
that your application might need,
set up notification observers and warm
up any services you might need later.
It's important to note that at this time your application is
not yet active.
Next we have application did become active.
This will be called each time your application is brought
from the background to the foreground
or after first launch.
This is a great time to start any code that needs
to be running only while your application is actually active,
activate any timers you might need
and especially update any state
that might have changed while your application was either
in the background or not running at all.
Application will resign active is called prior
to your app resigning being active,
moving to the background.
You want to prepare to be in an inactive state.
If you have started any timers,
this is a good place to pause them.
If you choose not to pause them at this time, they won't run
in the background, you won't get background running time,
but you will lose control
over the exact cycle in which they run.
So if you want control over that, it's a good idea
to pause them when you become inactive
and restart them specifically on did become active.
And you want to save your application state at this time.
Because after this point, your extension may be killed
if another process on the system needs that memory.
So in summary, WK extension delegate will help you
to track your application life cycle.
It's very important to note that this does have not have anything
to do with your notification UI, your glance UI,
or your complication data.
This is only about tracking the application's lifecycle.
Next up I would like to talk about handle user activity.
Handle user activity is an existing call from watchOS 1.
In watchOS 1 it was used when application was launched
by a tap on your glance to navigate
to the appropriate location in your application
that was reflected from the glance.
We are building on that in watchOS 2 in two ways.
First is that this will also be called
if your application is launched by a tap on your complication.
So similarly any state you reflected
in your complication you will want to navigate
to the appropriate place in your application for that state.
Additionally, we are moving it to WK extension delegate rather
than calling it on the root interface controller,
which is what we used to do.
This should give you greater flexibility with what you want
to do to handle your state maintenance.
So we have a new call on a new object called WK extension.
The new call is root interface controller, which I have
to warn you this is coming in a future seed.
It's not in the existing seed.
So in order to approximate this for now,
you'll have to save off your interface controller
when it's first created.
With that in mind, here is how you might implement handle user
activity on you are WK extension delegate for now.
I will get the root controller with the new call,
pop back to the root and then I will ask the root controller
to go ahead and do whatever it is that would be appropriate
to restore your state.
Note there are lots of other things you could do here.
You might put up a modal alert or other things
to handle the user activity you have been handed.
Next up, on IOS we have UI application
which is a singleton object
that represents the running application.
So on watchOS 2 we have added WK extension
which is roughly analogous to that.
Among other things this is the main interface
for opening standard system URLs.
So you will be able to open the open system URL API to do things
like start a phone call, send a text message
or display PassKit UI.
That's open system URL and WK extension.
Now, I would like to talk a little bit about notifications.
First, I would like to talk about remote notifications.
Remote notifications come from the internet,
and they always go to your phone first.
At that point, your phone will decide whether
to display the notification itself or whether to forward it
on to be displayed on the watch.
Now, the phone uses a set of rules to determine this,
and the criteria in these rules include whether
or not your phone screen is locked and whether your watch is
on your wrist and unlocked.
So like watchOS 1, your WK user notification interface
controller is run when a notification is received
for your app while it is inactive.
When this happens, one of these calls,
did receive remote notification
or did receive local notification, will be called
on your controller, and it's up to you
to call the completion handler in a timely manner.
If you take too long, your default interface will be shown,
which is a little bit less lively.
So it's up to you to do this in a reasonable amount of time.
Next up, I would like to talk about local notifications.
Local notifications must be fired on the phone
by your iPhone app, but you can message your iPhone app
from your WatchKit extension and ask it
to fire the local notification.
The same logic will be applied as for remote notification,
where the phone will decide whether
to display the notification itself or whether
to send it back to the watch to be displayed there.
So let's walk through an example
of how you would go about doing that.
Here, I'm going to use watch connectivity send message call
to send the message from the watch to the phone app.
When my iPhone app receives that message,
it can fire the local notification
to kick off the normal logic to determine
where the display the alert.
Relatively simple code.
So now we have the alert visible on your watch.
I would like to talk about launching your application
from your notification UI.
The app can be launched in two ways from here.
Either you can launch from a notification action button
which in this case I have set up with the reply button.
The user can also launch the application for notification
by tapping on the application iCon in the upper left corner.
When one of these actions happens
or when the user does one of these things,
one of these calls will be made on your WK extension delegate,
either the handle
with identifier call will be made either for remote
or local notification.
You will receive the identifier of the action that was tapped.
If they tapped
on the application iCon you will receive a nil for that,
and in the remote case, you will get a dictionary containing
In the local case, you will receive the UI notification
object that you created in the beginning
to fire your notification to begin with.
So that's launching your app from a notification.
Next, I would like to talk
about inline notification text replies.
In iOS 9 and watchOS 2 we have added third party support
for inline notification text replies.
In this example, the reply action has been designated
as having text input behavior.
When the user taps this action, instead of launching the app
or sending a signal back to your iPhone app,
the user will be presented with text input UI.
So you can see in this UI the user is able to tap
on the microphone in order to dictate the response,
they are able to tap on the emoji iCon in order to enter
from the emoji picker, or pick from a list of suggestions
which you as the app developer will be able to supply.
And the way you will do that is by implementing suggestions
to response to actions identifier call
on your WK user /notification interface controller.
So once the user has selected,
or has provided their text input either through one
of your selections or one of the other methods,
your application will be launched,
and you will receive this handle action with identifier call
on your WK or your WK extension delegate.
You will note that this variant has a new parameter,
the response info, and the response info will contain the
text that the user entered
in the UI user notification action response typed text key.
So another new feature I like to talk about is
on the fly language selection.
Here you can see we have standard text input.
Any time the user has the standard text input UI up,
they can choose to do a Force Touch to bring
up a language chooser.
The language chooser will offer an option
of all languages that are available.
These are selected based
on the keyboards you have made available on your iPhone.
So I have made English and Spanish available.
So I will go ahead and switch to Spanish
which will switch the text input UI to Spanish and allow it
to populate with a list
of Spanish suggestions instead of English ones.
So that's on the fly language selection.
Next up I would like to talk about another way
to handle notifications.
In watchOS 1, whether your app was active or not,
we would always instantiate your WK user notification interface
controller, and the system would display that over the top
of whatever was on the screen including your own app.
In watchOS 2, if your app is active,
we will no longer be doing that.
Instead the WK extension delegate will receive a did
receive notification calls.
It will be up to your app to handle, to display the contents
of the notification as appropriate.
So, for example, if you are writing a chat app,
you might append the contents to the end of the chat transcript.
Again, the system will no longer be putting up the alert for you
so if you want the user to know the notification happened,
you need to present it in your UI.
Next I would like to talk about modal alerts.
In WatchOS 1, you could unhide a hidden group to show an alert.
In watchOS 2 we have allowed present alert controller
with title which should make it much easier
to present modal alerts to users.
There are three variants on this call.
The first one is alert.
This is a simple call for telling the user
that something has happened.
Next we have the side by side buttons alert.
This is presenting either-or options to the user
and we think the third-party developers will want to use this
in their application as well.
And finally, we have the action sheet.
The action sheet can have
up to four main actions plus a customizable cancel action.
You can see the never mind,
the action I have customized to be never mind.
Actiions can be optionally marked destructive
which I have done with the delete button.
Currently that means they will be displayed in red.
Once the user selects from the cancel or one
of the four main actions you will receive a call back
indicating which one was selected.
So in summary, we have got a new architecture it watchOS 2,
we've added WK extension delegate
to help you manage your application's lifecycle.
We have got a whole host of new APIs.
And, of course, there is more to come.
If you -- for further info on the things Andrew
and I have talked about here, please check
out the documentation, the sample code
and if you have specific inquiries,
please contact Jake Behrens at this address
and there is a whole host
of related sessions including the next session in here
which is part 2 of this talk.
So thank you all very much for coming.
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.