WWDC2015 Session 108

Transcript

X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
(Applause)
>> 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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
during development.
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
as such.
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
Finish Launching.
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
get deallocated.
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
Okay. Great.
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
use WatchConnectivity.
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,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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 --
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
Okay. Great.
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So let's just open up my
Watch sim, place that here.
Press Record.
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
using Instruments.
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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 amazing.
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
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.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
(Applause) Thank you.