WWDC2019 Session 219

Transcript

[ Applause ]
>> Hello. Welcome.
My name is Matthew Koonce
and I'm an engineer
on the watchOS Frameworks Team.
I'm thrilled to be here today
alongside my friend and
colleague, Josh Weinberg, to
talk about how we can use
SwiftUI to build some really
amazing experiences that happen
right on your wrist.
Since our humble beginnings in
watchOS 1, the Apple Watch has
evolved significantly, and
watchOS has evolved right along
with it.
Over the years, we've been
adding some really great APIs
and features that have enabled
all of you to build some really
awesome experiences.
But that is just the beginning,
because with watchOS 6, we've
brought the platform to a whole
new level.
With independent apps, we've
decoupled the iOS and watch OS
experiences.
And for the first time, your
apps can be downloaded right on
Apple Watch with the new app
store.
We've also added support for
some new APIs like streaming
audio and extended runtime
sessions.
But we've also brought something
super awesome, and that is the
full power of SwiftUI to
watchOS.
[ Applause ]
With SwiftUI's powerful
declarative syntax and its
integration right into Xcode's
canvas, it's never been easier
to express the views that you
want to build.
And on watchOS, it means that we
have a whole new UI framework.
And with it comes some really
awesome features, APIs, and just
a whole new world of
possibilities for things that
you can build.
For example, with Lists, we
finally brought support for
swipe to delete and drag to
reorder.
And with SwiftUI's powerful
animations, you can create
completely complex,
interruptible, and custom
animations happening right on
the watch.
Now, SwiftUI is fully integrated
with WatchKit, which means that
you can have SwiftUI views that
live right alongside your
existing WatchKit interface
controllers.
And we have enough support for
embedding some WatchKit provided
interface objects directly
within your SwiftUI view
hierarchies, like the brand-new
sign-in with Apple button.
In fact, SwiftUI has really
robust support for integrating
with all of our existing UI
frameworks.
And we have a whole talk
dedicated to the topic that I
highly recommend that you check
out.
All right, so SwiftUI is fully
immersed in the watchOS
experience, which means that you
can use all those great APIs you
have with watchOS 6 and all
those awesome things we've been
adding over the years.
Whether you're using a streaming
audio app, you're using our new
extended runtime features, or
you're creating something
completely new for the platform.
For the first time, we have a UI
framework that works on all of
our devices.
Whether you're developing for
the 38 mm Apple Watch or
creating something for a 65 inch
television, all of it can be
done with SwiftUI.
But the Apple Watch is a unique
device and it has its own
considerations when building an
application.
Creating for Apple Watch is more
than just creating a
miniaturized version of your iOS
app, it's about distilling down
what makes your experience
great.
An Apple Watch is a highly
personal device and provides
easy access to vital
information.
So while your iOS app may be
used for a couple of minutes
while you're waiting in line at
the grocery store, on Apple
Watch, the interactions are
typically a bit shorter.
People see information at a
glance and respond with just a
few taps.
All right, so creating for Apple
Watch may start in your
application, but it's about
building an experience that
spans all these different touch
points we offer throughout the
system.
Whether you're creating a
dynamic notification, using Siri
relevant actions to show timely
information right on the watch
face, or using complications.
So that experience is really
important to Apple Watch and
defining that experience is even
more important.
That experience should be a
couple of different things.
And it should be contextual and
timely.
Showing the right information to
your users at the right time.
It should be highly legible,
showcasing beautiful design
right on the watch screen.
And it should prioritize quick
interactions, getting things
done with just a few taps.
Which brings us right back to
SwiftUI, because SwiftUI, you
can finally build those
experiences that you've always
wanted to build for Apple Watch.
So today we'll take a look at a
couple of different ways we can
use SwiftUI on watchOS.
First, we'll see how we can use
SwiftUI in an application, build
an engaging and highly
interactive notification, and
harness the power of the digital
crown to create tactile
experience.
So let's get started by looking
at an app.
And let's look at an app that
Josh and I have been working on.
All right.
So here I am in Xcode and the
app Josh and I have been working
on is called Pop Quiz.
It's a flashcard app that lets
me take my studies with me
anywhere.
And what I have open right now
is my interface controller.
If you've used WatchKit before,
interface controller will feel
familiar.
And this is an interface
controller, but it's a bit
different.
First, this interface controller
is subclassing WK hosting
controller, which is a type of
interface controller that is
provided by SwiftUI.
Now, because this is a type of
interface controller, I can use
this interface controller
wherever I'm using other
interface controllers.
For example, this one is set up
in my storyboard to be the
initial interface controller for
this app, making this interface
controller the entry point for
my application.
But, for example, if I wanted to
use a paging interface, in my
storyboard I can set up my
interface controller here to be
paged among side other WK
interface controllers.
Which gives it a nice
interoperability between
WatchKit and SwiftUI.
I can also push to this
interface controller using the
same WatchKit interface
controller push APIs.
Or I can use SwiftUI's
navigation button and give a
destination of an interface
controller name and push to
WatchKit from SwiftUI.
Okay. So let's go back to this
code.
So one other thing you might
notice here that's a bit
different from using WatchKit is
that there's no IB outlets.
That's because with WB hosting
controller and SwiftUI, our
entire applications interface
controller's views are defined
with SwiftUI.
That's so awesome.
So something else that's new
here is this use of the body
property.
And this is a type of property
that's provided by WK hosting
controller.
And we override it here.
This body property lets us
specify which SwiftUI view we
want associated to our interface
controller.
And in this case, it's our topic
list, which is just a list of
topics I have of different
flashcards.
And you can see a preview of it
over here on the right side.
All right.
So let's go dive in to our topic
list.
So as the name implies, our
topic list is a list.
And this list says, for each
model -- sorry, for each topic
in my model, I'm creating a
navigation button that's going
to go to another SwiftUI view,
in this case, the flashcard
list.
And it creates a topic cell.
And I'm using this list row
platter color modifier, which is
what's putting that color on
each of these cells.
If I go down here to my topic
cell, you can see that's pretty
simple right now.
Right now it's just using my
topics title and it's being
modified to use the System
Rounded font, which looks
gorgeous on Apple Watch.
Okay. One other thing to note
here at the top is this use of
app object binding.
App object binding is how I'm
letting SwiftUI know that this
model is the source of truth for
this view and that my view
should be updated whenever this
model changes.
Now, understanding how data
flows through SwiftUI is a
fundamentally important topic,
and we have a whole talk
dedicated to it called Data Flow
in SwiftUI, and I highly
recommend that you check that
out.
For now, what we need to know is
that this is how I'm keeping my
model and my list in sync.
So let's go ahead and make this
preview live by pressing the
play button here.
The application comes alive and
I can scroll it right within
Xcode.
And you can see, by default, we
have a pretty well-behaving
application.
Just by using list, we're doing
some really cool things under
the hood, like giving this
really nice animation here as
the list scrolls, we collapse
the cells and it feels like your
content is just flowing right
off your wrist.
All right.
So there's been a couple things
I've been meaning to do to this
list, let's go ahead and do
those now.
First is I have -- I want to add
a label to each of my -- in my
topic cell here that just shows
the count of cards I have for
each of my topics.
Just so I can see at a glance
like how many morphemes do I
need to study.
Let's go ahead and just do that
now.
And to do that I need a VStack.
Well, the editor in Xcode makes
that super easy to do.
I can just command click on my
text here and bring up the quick
action menu.
And I can select the embed in
VStack option.
The code is inserted.
And now below this text, I can
add the count of cards I have.
And you can see the preview
updates right away.
Now, you can see that VStack
aligns center by default.
And in this case, I want a
leaning alignment.
Again we can do that with the
editor.
If I select this VStack, command
click on it, and select the
inspector, I get this window
that shows me different kinds of
modifiers I can apply to this
VStack.
And in this case I want to use
the leading alignment option.
You can see the preview updates
again right away.
It's just super fast.
Now, we're using the leading
alignments and trailing
alignments in SwiftUI, because
by default we support right to
left languages.
If I have a localizable strings
file on my project that has
Arabic or Hebrew, by default,
this entire app's user interface
will flip and will support right
to left languages by default.
All right.
So there is actually something
else I want to add here, which
is like a symbol I have
associated to each of these
topics.
And I want that to appear on the
leading side of both of my
texts.
And I can do that with an
HStack.
So, again, let's use the editor
here, command click on this
VStack, and select the embed in
HStack option.
And then I can insert my symbol,
which is just an emoji.
Now, that's a bit small, I'd
actually like that a bit bigger.
So, again, I can return to our
now familiar inspector, command
click on this text, bring up the
inspector.
And you can see I now have
different contextual options.
And I can select here on my font
a title font.
And these inspectors make it so
easy to learn and like how to
add and modify this code,
because it's adding real code
into my code base.
It's not changing a POS file on
my storyboard, it's actually
teaching me how to write good
SwiftUI code.
All right.
So with just a few lines of
SwiftUI code, we've built out
this cell a bit more.
And, again, this entire time
it's been running live right in
Xcode.
I have a need to build and run
this app.
This kind of iteration is just
so powerful on Apple Watch.
We can finally get this really
quick design flow going and I
don't need to like do a
round-trip to the device.
Okay. So there's something else
in SwiftUI that's brand-new with
it and is unique to Apple Watch,
and that's an entirely new way,
new style of scrolling.
So to do that, let's first add a
bit of height to each of these
cells.
I'll go back to the inspector
here and go to my height, and
out of height, elect 100.
The preview updates.
And now I can go to my list.
And this new style of scrolling
is called the Carousel style.
With just one line of SwiftUI
code, we've completely
transformed the way that this
list scrolls.
If I go ahead and scroll it down
in the preview, you can see that
each of these cards now centers
right in the middle of the
screen.
This gives our users a nice
sense of place.
As they're scrolling this
content, it let's you bring
focus onto each of the elements
in the list.
Now, I decided to use this type
of scrolling for Pop Quiz
because we only have a handful
of elements in this list.
And I can make each of them big
by using a frame.
And this is where the Carousel
style really shines.
The Carousel list style is also
a great option if you have
interactive elements within each
of your cells, because it gives
that nice bit of focus and lets
our users have nice big tap
targets.
Okay. So there's also two new
types of interactions we've
added with List, both of which
are brand-new on Apple Watch.
The first is the ability to drag
to reorder.
Now, we've made this really
simple with just one modifier.
You can add on move and pass on
move closure that tells it how
to update your data store.
In this case, just moving from
one element to the next.
And I can add a delete, a swipe
to delete.
What used to be a bunch of
delegate methods and setting up
swipe actions is just one line
of SwiftUI code.
So now I can scroll this list,
we have this really beautiful
animation, these really nice
built out cells, all this code
is right here, right next to my
preview.
And I find a cell I want to
delete, I can just swipe it
right in the preview and delete
it.
It's just so cool and so
powerful.
[ Applause ]
All right.
So that was how we could use
SwiftUI in our topic list and to
build out these really great
interactions that were just not
possible before on Apple Watch.
But that's just the start of
what's possible on SwiftUI and
Apple Watch.
To see how to take your
experiences to the next level, I
would like to invite Josh
Weinberg to the stage.
[ Applause ]
>> Thanks, Matthew.
So Matthew talked a lot about
how we can use the power of
SwiftUI to create amazing
interactions just for Apple
Watch.
But, as we said, the experience
on Apple Watch is about much
more than just the application.
To build an experience on Apple
Watch, first I want to dive into
interactive notifications.
Now, interactive notifications
on Apple Watch are the primary
way which you have to provide
timely and contextual
information to your users.
On Apple Watch, notifications
are made up of two primary
parts.
The first is the short look.
Now, a short look appears
immediately upon registries and
will provide information
directly from the notification
payload.
This also includes your
application icon automatically.
After looking at the short look
for a period of time, it will
transition automatically into
the long look.
The long look is a scrolling
interface which allows you to
specify both a custom body as
well as these notification
actions below.
Here you're seeing a beautiful
implementation from Yelp where
they've created a complete
reservation confirmation
experience completely within
their notification.
To see how we can extend Pop
Quiz to really live up to its
name, let's add a notification
which will place a flashcard
right into the body to make sure
I'm keeping up on my studies.
So where I want to start is in
the notification controller.
The notification controller was
provided by the template when we
created this project by just
selecting the include
notification checkbox.
Very much like the interface
controller, this is new, it's
part of SwiftUI, but it comes
from the WK user interface
controller underneath.
So this new user notification
hosting controller provides the
entry point for interactive
notification and allows us to
provide SwiftUI content.
If you've used these before,
it'll be very familiar and you
have the same did receive method
coming from the user
notification framework.
The did receive method allows us
to extract information from the
notification, store it within
our interface controller, and
also provide those notification
actions that appear below the
notifications' body.
And then much like the interface
controller, we have the same
body property.
The one difference here is,
after did receive is called,
we'll automatically invalidate
and reevaluate your body
property so that your
notifications' view is
completely up-to-date.
To see what this notification
looks like, let's jump in to the
notifications' view.
Now, here we'll have a preview
of what this notification
appears, but it's not really
super useful if I'm trying to
study.
Here at the bottom we can see a
flashcard view which is showing
you both the question and the
answer.
To build this out and make it
feel a little better, I want go
and pin this preview, using the
pin button in the bottom left of
the canvas, and then go look at
the flashcard view.
And so now we can see I'm
building my flashcard as well as
seeing what it will look like in
context when I'm all done.
So I've already created some
views which I can place into my
flashcard to make this look a
lot better.
So the first thing I want to do
is replace both of these texts
by wrapping them within this
side.
Now, a flashcard has two sides.
So let's wrap this in both
sides.
And we've gotten this really
nice chrome around my flashcard
and all the default styling that
I'd want for any content which I
put inside of them.
But I can still see both sides
at once, and I'm really trying
to get better at studying.
So I want to replace this VStack
with a custom container which
I've written, which I call Flip
View.
Now, the Flip View provides all
of the transformations as well
as the interactivity, which
we're going to look at in a
second.
And all of the source code for
this will be available after the
conference, a sample code.
So to see what the notification
looks like in practice, we can
build and run using the
notification scheme which was
included as part of the Xcode
project.
And we'll see that the short
look appears.
We transition directly into the
long look, which looks exactly
like our preview like we'd want.
We get these notification
actions below.
And as promised, the
notification is fully
interactive.
I can tap the flashcard to flip
it over or even drag to interact
directly within the notification
body.
[ Applause ]
Now, that was really easy
question, and I definitely got
that one right.
So we've seen with taking
advantage of the same technology
that we've used to build the
application, we can create rich
and interactive experiences
within the notification.
Finally, there's one more piece
of the Apple Watch which I'd
like to talk about, which is the
digital crown.
Now, you've already been able to
take advantage of the digital
crown within your WatchKit
applications using the
WKCrownSequencer API.
This API allowed you to do some
very limited things with the
crown, digital crown, but we
want to be able -- we want you
to be able to create interfaces
much more like the ones which we
create in our own applications.
With Apple Watch Series 4, we
introduced a brand-new haptic
crown.
The haptic crown, digital crown,
provides feedback as content
scrolls on the screen.
This provides some really nice
resistance and weight to each
element, allowing the content to
feel more connected to the
digital crown than it ever had
before.
We've already taken advantage of
this all across our own
applications.
For example, in workout, where
we have this beautiful list
where the elements have a lot of
weight to them as they scroll
by.
Or when you're creating a custom
timer and you have these pickers
where as you fly through, it
provides haptic feedback.
In SwiftUI, we've provided
system components that give you
this all out-of-the-box.
For example, list, picker, and
scroll view will do all of this
for you.
But if you're going to build
something a little more custom,
we have some new modifiers as
part of SwiftUI that allow you
to realize these visions.
The first kind custom interface
I want to talk about is what we
call a free scrolling interface.
In a free scrolling interface,
you don't really have concrete
stops between your content, and
instead you want to be able to
stop anywhere along the sequence
which the digital crown is
moving.
To implement something like
this, you use the new Digital
Crown Rotation Modifier,
provided by SwiftUI.
In its really simple form here,
it only takes three parameters.
The first one we need to worry
about is the binding.
Now, like any other SwiftUI
component which takes a binding,
this provides the source of
truth for how this modifier
interacts with the system.
In the case of a free scrolling
list, we might want to bind to
the offset of the view which
we're moving.
We also need to tell the digital
crown where we're going from and
where we're going through.
These define the limits of the
sequence over which the digital
crown will move.
To see what this looks like in
action, we can see that now as
we move the digital crown
represented by the red dot,
we'll provide linear feedback as
well as some nice haptic
feedback in a rubber banding
behavior at either limit of the
digital crown's sequence.
Next, if you wanted to build
something a little more custom
-- for example, like this
picker, which we've provided as
part of -- which is included in
the new calculator application.
We're here, we're no longer
scrolling content.
Instead we're picking between
discrete elements and using the
digital crown to move from one
to the next.
We can use the exact same
Digital Crown Rotation Modifier
with many of the same
parameters.
Now, these parameters -- instead
of going over scrollable lists,
we're selecting between the
number of people and going from
1 through 15 of them.
Now, the new parameter here is
the by parameter.
And by allows us to specify the
stride along which the sequence,
the digital crown sequence, will
provide that haptic feedback and
settling behavior for you.
To see what this looks like, we
can see now that the digital
crown will provide haptic
feedback as we go from one
element to the next, and it's
just that easy.
And finally, if you wanted to do
something even more custom --
for example, the interface that
we've had in alarms.
Where here the digital crown is
controlling a view which is
moving around a circle.
It's no longer limited at either
end of its sequence.
Here, we come back to the
familiar Digital Crown Rotation
Modifier.
This modifier takes all of the
same parameters which we've
already been talking about, as
well as I want to introduce two
new ones.
First is sensitivity.
Sensitivity allows us to specify
how much rotation we need to
apply to the digital crown to
move from one element to the
next.
And finally, we have the
continuous parameter.
This parameter allows us to
specify that we no longer want
the digital crown to stop at
either limit of its sequence.
In action, we can see now we
have this really nice
interaction where we can go all
the way back around and continue
moving the digital crown in one
direction.
There's no more limits to the
sequence.
Finally, to let the digital
crown get its input, we need to
tell the system how to get it
there.
To do that, we introduce the
focusable modifier.
Now, focusable will feel very
familiar to you if you've used
other UI frameworks which we
provide.
This is a lot like the UI Focus
Engine in UIKit or First
Responder, which I'm sure
everyone here has used before.
And by just adding this
focusable modifier, we can now
use the digital crown to update
the people picker, tap over to
tip, and continue using the
crown to update the now focused
view.
To learn a lot more about how
focusable works, please go check
out the SwiftUI in All Devices
talk.
To see how we can take advantage
of this and to build some really
awesome interactions in Pop
Quiz, let's go back to demo.
So Matthew had already shown the
really nice card list at the
entry point of the application
-- or the topic list at the
entry to the application.
But I want to build out a really
cool card list.
Now, we already have a nice list
here where we're seeing these
flashcards in a scrollable view,
which we can still see in the
preview.
But wouldn't it be nice if we
had a really cool, custom
interaction driven completely by
the digital crown?
To do that, what I first want to
do is replace the scroll view
with a ZStack.
Now, we'll see that flashcards
are no longer stacked vertically
but instead stacked one on top
of each other.
But I promise you that every one
of them are still there.
Next, because we're going to be
building something using the
digital crown, we need to supply
the focusable modifier as well
as the Digital Crown Rotation
Modifier.
Now, there's a lot of parameters
here, but these are the exact
same parameters which we've
already just talked about.
So let's go through them one by
one.
First we're going to need to
supply a binding, or the source
of truth where the digital crown
will be updating its value.
To do that, we need to provide
some state.
Here, I want to provide the
current index into which this
custom interaction will be
moving between.
Next we supply that binding to
that state back into the digital
crown rotation.
Here, I want to use an animated
version of that binding, so as
the digital crown updates, it
refreshes this view in an
animated fashion.
Next we need to specify how far
we're going from as well as
where we're going through in the
sequence.
Here, we're going to the second
to the last card in the sequence
to achieve the effect which
we're going for.
Next we need to specify the by
value, which is the stride
between each of these cards, as
well as the sensitivity.
Which here, I want to specify a
low sensitivity so that each
card gets a lot of weight to it
and I can make sure I'm looking
at the card which I want to look
at.
And then finally, to actually
get the nice effect we want to
look at, I've already written
this Card Transform Modifier.
Now, this is a custom view
modifier which I've already
written, which will provide all
of the 3-D effects and allow the
card to update with the current
index.
And we're passing in the current
index into this modifier so that
it's updated every time this
view is re-rendered.
And that's it.
Now we can go build and run this
application.
And as it comes up in the
simulator, we'll see the same
view which Matthew had already
showed us at the beginning.
We can go through this list,
select what we want to see, and
see that now we have this nice
interface which we can scroll
through using the digital crown.
And that's it.
And if anyone does know the
answer to this question, please
let me know, I'm really looking
to get the answer.
[ Applause ]
So that was awesome.
We've seen how we can build some
really great experiences using
SwiftUI and to take advantage of
everything that the Apple Watch
has to offer to get us there.
But there's more to it than
that.
Now we have the same UI
framework across all of our
platforms.
You can take the same concept
you've learned building your
awesome iPhone application and
apply them directly to building
experiences on Apple Watch.
We really can't wait to see what
you build now that you can make
the interfaces you've always
wanted to make on Apple Watch.
There's a ton of great sessions
to talk about SwiftUI at the
conference this year.
And to learn more about how to
make those 3-D animations,
definitely go check out the
Building Custom Views with
SwiftUI talk.
Enjoy the conference.
Thank you.
[ Applause ]