Building Watch apps with Xcode 7 is easy and straight-forward. Learn how to build and debug a Watch app for watchOS 2 from the ground up. Walk through adding a Watch app to an existing application, building the user interface, debugging and profiling with Instruments, and discover how to efficiently communicate between iPhone and Apple Watch.
NEIL DESAI: Hi, everyone.
Welcome to Building Watch Apps.
My name is Neil Desai, and I am an engineer
on the watchOS program.
Today I am going to show you how
to build a watchOS app from the ground up.
So we're going to talk through the architecture of a Watch app,
we are going to walk through the app life cycle,
the layout model.
We are going to use those different interface elements
to provide a great experience for your user.
We're going to debug the app, and we are also going
to enhance our app using various watchOS 2 features.
So, on the Apple Watch you have four opportunities
to present information.
From the Home screen on Apple Watch
to where it can manually launch your Watch app.
The Watch app offers an in-depth user experience
and where you will focus most of your development efforts.
You can optionally provide a Glance,
which offers the most timely and relevant data from your app
in an abbreviated form.
You can also provide a custom UI for your app's remote
and local notifications.
Apple Watch takes advantage
of the existing interactive notification support on iOS
to allow the wearer to respond with a specific action,
transition to a specific area of your app,
or later view the notification
in Notification Center on Apple Watch.
And lastly, you can add -- now you can add a Complication
to display information on the clock face, and this is one
that I am really excited about.
This is great for small pieces of information
that the user may want to know while viewing the time.
So now that we know the different ways the user will
interact with your app,
let's discuss the architecture of a Watch app.
Your existing iPhone app contains your WatchKit extension
and Watch app.
These both get installed on the Watch after initial pairing
at the user's request or a later user-initiated installation via
the Apple Watch app.
The Watch app is comprised of two pieces, first,
the WatchKit extension, and this extension now runs
on Apple Watch and executes code
in response to user interactions.
The second piece is the Watch app.
Your Watch app's UI is loaded
from a bundle containing your storyboard
and static resources such as images.
So this UI, which lives in the Watch app,
then talks to your WatchKit extension,
where you can place all of your logic.
Now that the extension lives on the Watch,
you can enable all sorts of new capabilities,
which I will get into later.
And in the moments when your Watch app needs to communicate
with your iOS app, there's a new framework called
WatchConnectivity that you can use to offload heavy processing
or networking tasks, and WatchConnectivity lives
on both iOS and watchOS 2 so you can communicate back and forth.
To summarize, your storyboard and all
of your static resources are stored in the Watch app bundle.
The Watch app target provided to you
by Xcode already contains the storyboard you'll use
Because these resources are part of the Watch app,
they must all be specified at design time
and can only be modified slightly at runtime.
This means you need to incorporate all
of the UI elements that you might need
into each scene of your storyboard.
At runtime, coding your WatchKit extension can update those UI
elements, including hiding, showing,
or animating them as needed.
Additionally, your WatchKit extension can send dynamically
generated content over to the Watch app for display.
So in Interface Controller manages the UI elements
for a single stream of content.
It sets the initial values of those elements,
responds to user interactions,
and updates the UI as appropriate.
When you create your Interface Controller subclass,
you add outlets for each UI element you need to manage.
These outlets connect to objects in your storyboard
and handle the transfer of information
between your WatchKit extension and Watch app.
In addition to outlets, you set up action methods
for the interactive elements of your storyboard,
and as with outlets, you connect each action method
to the corresponding UI element.
And when the wearer interacts with that element on the Watch,
WatchKit will then call your action method.
So let's get started thinking about how
to modify an existing iPhone app.
So in the run-up to WWDC, I have been a little forgetful
about contacting people such as my family and friends,
so I wanted to create an app that reminds me
who I have contacted and who I haven't,
and it's called WWDC Call Me Lately and helps notify me
when I should contact them.
So I communicate with my server to keep track
of the people I need to contact via NSURLSession.
This is a great iOS app I made, but really,
it makes even more sense as a Watch app.
When I am busy, I quickly can know who I need to contact next.
Let's get started making our Watch app.
So what I want to do is I want to show you how
to add a Watch app target to an existing iOS app,
and then we are going to walk through where
to get started configuring your interface.
And lastly, we are going to build and run
to see how things look in the simulator.
So speaking of the simulator,
we actually have a brand-new simulator in the watchOS 2 SDK.
So you guys are all probably familiar with the iOS simulator,
and it looks something like this.
And now we have a new Watch simulator.
So what's great about this is it's a fully fledged simulator,
so we can easily look at our 38-millimeter
and 42-millimeter sizes.
We can simulate touch pressure.
We can also look at different clock faces.
So like I mentioned earlier, there's now the ability
to support Complications in watchOS 2, and so you can look
at how your Complication views
in different clock faces in the simulator.
And lastly, you can have multiple apps installed
at the same time.
So we think this is going to be a really great way for you
to easily make a new project, iterate on an idea,
and then quickly go back and forth between different apps.
So to simulate touch pressure, you go into the Simulator menu,
and you go to Hardware, Simulate Touch Pressure,
and then you can select the Deep Press.
This is useful for things like wanting
to change the clock face in the sim.
Now let's jump into Xcode and see how we can add our Watch app
and use this brand-new simulator.
So let's go to demo.
Great. So let's launch Xcode.
And let's select our app.
And let's make this a little bit easier to view.
Great. So now if I wanted to add a new app, I would just go
to File, New Target, and then I now have a new watchOS pane,
so I have an application and framework in library.
I select Framework In Library so I can add a Watch framework
or Watch static library.
For now I am going to add a WatchKit app.
I double-click, add a product name,
and my main app is always going to be enabled by default,
but I can also include a Notification scene,
a Glance scene, and a Complication.
So I can add those here.
I already added it to this app.
Let's just press Cancel.
Now let's see what we are given.
Here is our Watch app, and here is our WatchKit extension.
Like I mentioned before,
our Watch app contains our storyboard,
all our static resources, and our asset catalog.
Our WatchKit extension will contain all our interface
controllers and any other code we might want to add.
Let's go into the storyboard.
So now, as you can see, I have a main interface,
I have my Glance interface, and then I have my static
and dynamic interface for my notification.
Now, let's also go into the utilities inspector,
and I can look at the object library and see
that I have a lot of different objects here that I can use,
and I have all my WatchKit interface elements as well.
So let's just drag and drop an interface controller over.
For instance, if I wanted
to very simply make a page controller,
I could select Control on my keyboard and then drag
over to my new interface controller
and create a segue for next page.
So for now, we'll just get rid of that, and if you see below,
there's a static interface and a dynamic interface,
so the dynamic interface is actually what hooks
up to your Notification Controller class.
So when your user first raises their wrist
when they get your notification and then they see it,
your Notification Controller class will get called,
and you can provide a very rich UI there.
Now, your static interface is typically going to be invoked
when the user, for example, misses your notification
and goes to view it again in the Notification Center,
and that's typically when you will see the static interface.
So also, I have this My Category here.
So for different categories that we send for different payloads,
we can actually create custom UIs and custom notifications
for those different categories.
So it's not just one interface for one --
for all of the notifications you send.
You can actually modify this and create multiple interfaces.
So let's just add a new notification controller.
Let's place that here.
So if I wanted to, I could drag over an interface controller
and then, just like I did before, I would Control-click,
and then create my new dynamic interface.
Or I can also just go here into the attributes inspector
and select Has Dynamic Interface.
So now I can modify my category
and I can create a new interface,
and then I possibly would want
to create a new Notification Controller class
and then hook that up as well.
So also we have given to us
by the template a push notification payload .apns file.
If you see here, this looks just
like a normal payload we might have.
It has an alert, a body, a title, a category.
What's great about this is in the simulator,
we can use these different payload files
and mockup different interfaces.
If we want to test out all of these different notifications,
we don't have to just do it to device.
We can now quickly iterate
on different ideas using the simulator
and these notification payloads.
So let's go back to my storyboard.
So now I just want to build and run
and view my main app in the simulator.
So I am going to go up to my schemes,
and I see I have my iOS scheme and then my WatchKit app scheme.
And then I have two simulators here, an iPhone 6 Plus
with a 38-millimeter
and an iPhone 6 Plus with a 42-millimeter.
As I mentioned before, this is actually a full simulator
for the Watch.
It's actually going to be paired with my iPhone sim,
so let's select the iPhone 6 scheme, and let's build and run,
and now I have two simulators open.
So what I expect to have happen is that the main app will launch
and I will get attached to it in the debugger.
So great. So let's press Allow, because I do want to allow this.
And now I am attaching the debugger,
and I have a small thing that has appeared here,
it says "extension received request to wake
up for complication support."
So if I were to implement my Complication,
this would later go away.
So now let's just stop this debug session.
Let's go back to our Watch sim.
So here's my new simulator.
I have my clock face.
Now if I really just wanted to change out my clock face,
I can go into Hardware, Simulate Touch Pressure,
and now I can simulate a deep press, then I can go back
to a shallow press, and then I can modify my clock face.
Now I can customize my clock in the simulator.
So if I were to go to this screen on a device,
I would use my Digital Crown,
and then I would easily change the color.
So there isn't a Digital Crown on my mouse,
but thankfully I have a scroll wheel,
and I can use the trackpad or Magic Mouse,
and I can change the color as such.
Now I can simulate the Digital Crown behavior.
Also, when I am in my Complications view,
as I swipe over, I can then enable my Complication
that I have, and so if I am iterating on Complication ideas,
I want to build some new Complications
on different faces, I would just enable these Complications
So for now, let's just go back, and let's do Command-Shift-H
for home, and let's select and then do Command-Shift-H again.
So now I am at the Home screen, so I have my Settings app,
my clock face, and the app I have.
And then I can launch my app and see it as I expect.
So let's go back home.
And now, like I mentioned, these sims are paired.
I have two different sims to choose from.
I go into schemes and I see my two sims.
But what happens if I want
to have an iPhone 5 sim with a 42-millimeter?
I am going to make a new sim and have it paired for me.
So let's go into Xcode and then select Window, and then Devices.
And so now in my sidebar, I have all of my different simulators.
So if I go to the bottom left, I can then add a simulator.
So I can call it iPhone 5.
Change my device type.
I will keep my iOS version.
I will change the paired watch to be a 42-millimeter,
so I can easily create that.
Now if I go back to my scheme, there's my new simulator.
So let's go back to the storyboard.
And so as I mentioned, there's these schemes
that we can pick from, so there's a Notification scheme,
there's Glance scheme, and a Complication,
so I can select these different schemes
and quickly debug those parts of my app.
And now, for example, I want to just test
out my Notification scheme,
I want to see how it looks in the simulator.
We already talked about the APNS files.
I want to see that appropriately appear.
So let's just add a label to my dynamic interface.
And let's drag it over.
And let's just rename this Dynamic.
So now I selected my Notification scheme,
and I am just going to build and run this to the simulator.
So what I want to have happen is on the Watch sim,
my notification will appear, and then it says Dynamic,
and that's all it should say for now.
So here's my notification, and it says Test Message,
so I am going to look into my console.
It says "took too long to show custom notification.
Falling back to static."
Okay. So let me look into my notification controller
and see why that might have occurred.
Here is my code for my notification controller.
I go down.
Okay, so my Did Receive Remote Notification is commented out.
I should probably uncomment this.
And now let's just build and run again.
So now hopefully, after I dismiss the old notification,
I should then see my new one,
and it says Dynamic like I expect.
So on device, if I was in this scenario and got a notification,
I could select the App icon or button
and I would be taken right to the app.
So I can just do the same thing here in the simulator,
and I am taken right to the app as I expect.
So now I could flesh out this code and add a great UI story
in my notification, and I still want
to be testing my static interface.
The only way I just saw that happen was I had to comment
out Did Receive Remote Notification
to get my static interface, and I don't want to be doing
that while I am iterating on my code.
So there's a couple ways I can do this.
One, I can change this custom in my completion handler
to call Default, or I can actually go into my schemes,
I can edit the scheme, and now I can choose my Watch interface.
So I can change it to be a static notification rather
than a dynamic, and as you can see,
here's my push notification payload.
So if I had multiple payloads, they would appear here,
and I can quickly change
out which payload I am trying to test.
So for my purposes, I might want to keep a static scheme
around for a while, so I am just going to duplicate this scheme.
Let's call it Static Notification.
Then let's go to Run.
Then I change my Watch interface to be static.
Let's press Close.
So now I have a static notification as well
as my normal dynamic notification.
So this is great, and we have the beginning
of a template project here, but let's understand some context
of how the app life cycle works on watchOS.
So let's go through the life cycle of a watchOS app.
So we looked at the interface for the Watch app but haven't
yet observed its life cycle.
It's important to know when the extension
and interface controller get called for setup and tear-down
so you are configuring UI elements at the right time,
as well as performing cleanup operations or finishing tasks
when the wearer stops interacting with your Watch app.
When your Watch app is launched,
the extension delegate will get Application Did
The extension delegate is analogous
to UI application delegate on iOS.
As such, you will also receive an Application Did Become Active
callback to allow you to update your model data.
Next, the storyboard in your Watch app bundle is loaded
on Apple Watch, and the initial interface controller is created.
Once the UI is initialized,
your interface controller will receive an Awake
With Context call, giving it a chance to initialize variables
for state and configure UI elements
with their initial values.
When the UI of your Watch app is in the process
of getting displayed on screen, Will Activate will be called,
allowing you to perform any last-minute tasks
or final UI element configurations.
And now, as the wearer interacts with UI elements,
WatchKit calls the action methods you defined
on your interface controller.
Those action methods are your chance to execute code
and update your app's UI.
Keep in mind that engagement times are short.
On iOS, we traditionally think in terms of our user interacting
with our app in a sense of minutes, but on watchOS,
we are going to be thinking in terms of seconds.
Actually, we are going to hit a Did Deactivate call
after the wearer stops interacting with our app.
And after that method is called, then at some point
in the future, the interface controller will then
And now our extension delegate,
after the wearer stops interacting
with the watch completely -- for example, they might go back
to the Home screen -- you will receive an Application Will
Resign Active callback, and so this is your opportunity
to save any app-related state information and close
out any ongoing tasks.
So we know the life cycle of the WatchKit extension,
but another important thing to talk
about is the layout of the Watch app.
So the model in watchOS for WatchKit is different from UIKit
and AppKit because it's a flow-based layout.
So all of our elements go one after another,
and our UI is primarily created in Interface Builder.
So when we have an interface controller,
we can use our object library and just drag an image
or drag a button, and then in the instances when we want
to have a slightly more involved layout,
we could use a WK interface group,
which will just manage the layout for different items.
So for example, we could add an image
and a label into the group.
And so the programming model is really important to note.
You don't write object creation code with WatchKit.
You have fine-tuned control in the Interface Builder
of positioning and sizing, the layout hierarchy, and animation.
And I highly encourage you to go to the Layout
and Animation Techniques talk for WatchKit on Thursday.
It's going to be a great session on how
to create really rich UIs for your users.
And so I've been thinking about how best to make my Watch app,
and if you recall, my iOS app is just a simple UI table view.
So my first idea was to have a list of all the people
that I need to call, very similar to my iOS app,
and when I started thinking about it,
I realized I don't need all that information in my Watch app.
Really, I just want to know who next to call rather
than knowing a list of all those I should call.
So my UI might look something like this.
So great. Now I have an idea of what I want to make,
and I want to start creating my UI.
So I am going to walk through how to create your UI
for your main app, your Glance, and your Notification.
So let's jump into Xcode and see what we have.
So we understand what the life cycle is
and generally speaking what the layout is,
so let's go into our storyboard.
If I wanted to add an image to my interface controller,
I would select it here in the object library,
and then I can just quickly drag an image over,
and now I just want to add a label as well.
So let's just find the label and drag it over.
And if you notice, a blue line appears,
so in my flow-based layout, I can position my label to be
after or before my image.
So let's place it after.
Now, for instance, if I want to place them horizontally next
to one another, I could --
okay, so I can't actually do this in Interface Builder.
There's no blue line that appears to help me out.
So let me use a WK interface group to do this.
So let's drag this over, resize our image a bit,
and now let's add the label into the group,
and then let's also add the image right next to the label.
So this is how it can position things horizontally.
So for now, let's take our label out and our image out,
and let's just delete the group,
and then in my attributes inspector,
already in my asset catalog,
I have an image for my friend, Ethan.
So let's just reference that image.
Ethan looks a little squished.
Let's make him look a little bit happier.
There we go.
He seems pretty happy.
So let's also change the label text to be Ethan.
Now my layout is positioned -- it's left-aligned,
so I actually want to position it centered in the screen.
So if I just select on my image,
then go to my attributes inspector,
and I can change the position to be in the center.
Then I can also change the position vertically,
I can change the size, I can change the view
for this particular image, and I can do the same for my label.
I just want to position it in the center.
Now let's move on to the Glance.
If you notice, this Glance controller looks different
than our main app.
There's two groups here.
That's because Glances are actually templated.
So I have an upper template and a lower template.
So if I select in my attributes inspector my upper template,
I have a list of options that I can choose from.
So for this particular case, let's just have a large text,
and let's change it to be Call.
Then let's add an image to my lower template.
I am going to do the same thing as before,
just change the image to reference Ethan.
So when I look at my Glance, I really kind of want the app
to scream at me because I am really bad about calling Ethan,
so the app will help me do that.
And so also I can do the same thing
for my notification interfaces as well.
So for the most part, I figured out my new interface,
and now let's just build and run the interface
by selecting the schemes.
Let's build and run to the Watch sim.
So I just expect my new interface to appear.
So there it is, and I have attached in the debugger.
So let's just stop this session, and now let's take a look
at the iOS sim because it's important
to note these are paired devices.
So I scroll up, and I pan to the right.
I see I have my iOS app installed,
so just like on a device, the only way your app will get
to a user's Watch is by also being installed
on the iOS device.
And so this is what's happened here.
Now let's select our Apple Watch app, and in the simulator,
I can change out my Complications.
So Call Me Lately is already enabled.
I can also uninstall my app and reinstall it,
and I can also disable my Glance and reenable it.
So if I wanted to view my Glance,
I could go in the simulator, go back to my clock face,
and just like on device, I swipe up, and then my Glance --
so let's just reenable it.
So -- oh, excuse me.
So I would expect my new UI to appear.
That hasn't happened, but let's just move on for now.
So I figured out my new interface, but I need to know
who the next person is, and I need to figure out how
to update my app to do this.
So let's go back to slides.
So my iOS app mainly communicates
to my server via NSURLSession to get my list of loved ones.
What's great is in watchOS 2, I can use a lot
of the same NSURLSession code to talk to my server.
However, there are times when I need to make sure
that my iOS app and watchOS app are in touch with each other,
and I can use WatchConnectivity to do so.
So let's take a moment and talk
about the new WatchConnectivity framework before we see how we
can use it in Call Me Lately.
So WatchConnectivity is a framework
that has four core uses for communication
between iOS and watchOS.
An important thing to note is that WatchConnectivity lives
on both iOS and watchOS, so you can use APIs on both platforms.
This isn't just your Watch app talking to your iOS app
when there are times when you want your iOS app
to be updating your Watch app.
So the first use is to allow your iOS app
to update your Watch app's application context,
and vice versa.
This may not be urgent data, but something you know you'll want
to update your user with.
The second is Send Message.
This is for small pieces of information that I need
to transfer back and forth
between my iOS app and Watch app.
And the third is a simple transfer file API.
And lastly, there's a transfer user info API that ties in more
so with Complications.
There's also a wider range of things you can accomplish,
and I encourage you to go to the talk on WatchConnectivity
to find out more information.
Let's see in Call Me Lately how I can best
I just want to add WatchConnectivity to my app,
I want to debug it, and lastly I want
to just profile it with Instruments.
So speaking of Instruments, for those that don't know,
Instruments is a powerful profiling tool to check
out the performance of your app.
So you will get a profiling template
when you first initially launch Instruments, and you can pick
from a time profiler, leaks, allocations,
and then you will see something, if I select a time profiler,
for instance, this is the view I would see,
and I can easily profile my app.
And it's really important,
so engagement times are short on the Watch.
So this means that performance is critical,
and we want to be using Instruments to make sure
that our app is giving a good user experience,
and we want to check it out on both device and simulator.
So now that we know a little bit about WatchConnectivity
and Instruments, let's go into demo again.
So in my app, I might have an algorithm of sorts that says,
oh, this is the next person I want to call.
And so when I have this data available,
I want to update my iOS app to know who is the person
that I am viewing on my Watch
and the person I should next call.
So I might want to maybe on the initial launch
of the app just update my application context
over to the iOS app and see that appear.
So I would probably just want to do this
on my Application Did Become Active in my extension delegate.
So here I could just place this code.
So let me first import WatchConnectivity.
And now in Application Did Become Active,
I would add some code,
just create a context that's a string named Ethan,
and then on WC Session, which is part of WatchConnectivity,
I have the default session
and I call the method Update Application Context
with the key WC Application Context,
and I would just send over my context.
And worse comes to worst, I am just going
to print my error for now.
So let's see this work.
And let's build and run.
Let's select our Watch app.
My app launched, but I see a WC error domain, 7004,
so I know from previous experience
that my session just isn't activated.
Let's take a look at my code.
I also haven't set my delegate either,
so I want to set a WC session delegate, and then after --
or before my update application context code,
I just want to set the delegate to be myself, and then I want
to activate my session.
And it's important to note that you want
to set the delegate before activating your session
because you might have messages waiting for you
when you've activated that session.
So you want to receive the appropriate delegate callbacks.
So now let's just build and run again.
Now let's just make sure that my error code has gone away.
So I don't have my error anymore.
So that means this is appropriately sending my
application context to my iOS app.
But now I want to see that my iOS app actually receives it.
So I can do this by going to Schemes
and selecting my iOS scheme, and I am going
to select the same simulator that's paired with my Watch sim.
So I'm going to select my iPhone 6 sim.
Now if I click on Control and then press on Build and Run,
I can actually run without building,
so this way I don't have to -- if my app is really large,
I don't have to wait for it to keep compiling
and install the app, et cetera, et cetera.
So let's just press Control and then run without building.
So now it looks like my app launched, and I've hit
on my app delegate in my iOS app,
I've hit my delegate callback, Did Receive Application Context,
and I can then update my UI in my iOS app.
Let's just continue through.
So now if I am on my Watch sim, and let's go back home.
So my debugging session is still ongoing in my iOS app,
and my Watch app, when it's activated -- excuse me --
when it's launched, it will then update my application context.
So I can hit it again on my iOS app
and hit the delegate callback.
So this is great because you can now debug in both simulators
at once, which is really great
for when you are using WatchConnectivity,
so you can make sure all of your calls are occurring
in the order you want them to on both watchOS and iOS.
(Applause) Thank you.
Let's just stop the session for now, and I just want
to quickly profile an Instrument.
So I'm going to hit Product, Profile, and I am going
to have Instruments come up, and I expect my template to appear,
my template selection.
So let's find my -- okay.
Let's find my time profiler.
Let's just choose that.
And then instead of my iOS sim, I actually want
to be debugging my, profiling my extension.
Select that here.
I can press Record.
And it looks like I've hit an error.
So let's just open up my Watch sim, place that here.
And there I have attached, and now I can profile my app.
So in my call tree, I can also see my sample list just
like on an iOS app, I can do the same sorts of things,
and I can see that most of my code is being run
on my main thread here, which is great,
and then I can go back to my call tree.
And so this is just very simply you can easily profile something
So let's just stop this session.
And now I've written an app
that basically has a very simple interface
and uses WatchConnectivity,
and I've profiled my app in Instruments.
Now I could talk with my designer
and really flesh this out.
So let's talk about what we were just able to do.
So we added a Watch app to our existing iPhone app.
We created an interface for our app and Glance.
We used WatchConnectivity.
We debugged our iOS and watchOS apps at the same time.
And we profiled our app in Instruments.
So these are just a few of the things that you can get started
with in WatchKit, and there are so many other watchOS 2 features
that I am incredibly excited about,
and like I mentioned before, there's Complications,
and as you might have seen in the Keynote yesterday,
you can even do Time Travel,
which I think is just the future.
You can just, like, go back and forth.
It's so cool.
And then you can also use Digital Crown,
so you can create really intuitive experiences
for your users using the Digital Crown.
You also have simple animations to create really responsive apps
for your user, just nice and playful.
You also have access to the heart rate sensors,
so if you are making a Workout app or some sort of fitness app,
you now get that data via HealthKit and can use
that to provide a better experience for your user.
You can also provide a great experience using haptics
and lightly tap your user and provide some context
as to what you are doing in the app.
And there's also media playback, so like you saw
in the Keynote yesterday, you can view a simple video.
And you can also have audio playback as well,
so this would use the speaker on the Watch,
or if the user has paired Bluetooth headphones,
it would then route there as well.
And you can do audio recording, so for the first time,
you can get access to the mic on the Watch itself
and provide a great experience.
And you have access to the Keychain now,
so you can provide a really secure experience for your user.
So in recap, we were able to discuss the architecture
of an app, we added a Watch app,
we talked through the app life cycle,
we used the different interface elements and we made our app
and our Glance, and we talked
through our notification interfaces and how
to easily iterate on different notifications
and using different categories and different payloads.
And we were able to build and run in the new simulator,
and we debugged our app.
And we were able to use various watchOS capabilities.
So there's some great documentation online,
the watchOS 2 Transition Guide is excellent.
I highly encourage you guys to all check it out.
There's some great technical support.
You can check out the Forums, some sample code.
If you have general inquiries, please contact Jake Behrens,
our watchOS framework's Evangelist.
There is a lot of really amazing sessions happening this week,
there's a lot of info to dig through, WatchKit in Depth,
Complications, Layout, and so much more.
If you have any questions, if you have general questions
or you're digging into the code for a first time,
or if you are an experienced WatchKit dev, please come by,
we will be happy to answer any questions you might have.
So thank you, everyone.
(Applause) Thank you.
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.