SwiftUI On All Devices

Once you've learned the basics of SwiftUI, you've learned what you need to know to use SwiftUI anywhere. You can use the same SwiftUI skills for making an iOS app as you would for making an app on watchOS, tvOS or macOS. We'll cover the basics, and then dig into more detail about how SwiftUI can help you make changes to your app on every Apple device. Hear about design principles for each platform and learn about how much code you can share across platforms. See how to incorporate device-specific features and how to make changes in SwiftUI by following along with a starter project, available for download.

WWDC 2019

Welcome. It's so great to see
you all here and it's great to
see so many people excited about
SwiftUI.
My name is Jeff Nadeau.
I work on macOS frameworks and
I'll be joined in a little bit
by my colleagues Ada Turner and
Meghna Sapre [phonetic].

Now we hope you've had the
chance to learn about SwiftUI
all throughout the week but if
you need a summary, here it is.
SwiftUI is the shortest path to
building great apps on every
device.
And what we're here to focus on
today is the 'every' in every
device.
Now when we think about building
applications for all of our
Apple devices, these are the
technologies that we think
about.

We use AppKit on the Mac.
UIKit on iPhone and iPad,
TVUIKit which is built on UIKit
for Apple TV, and then on the
watch we use WatchKit.
These UI frameworks were
designed around the strengths
and capabilities of the
respective devices.

And so naturally there are some
differences between them.
And historically we haven't been
able to take code written for
one and move it over to another
device without modification.

But for the first time ever,
we're introducing a UI framework
that you can use on any of these
devices.
That's unprecedented and it's a
big opportunity for you as app
developers.
But these devices are so
different so how is it that
we've built one UI framework
that works on all of them?
Well, SwiftUI was built from the
ground up to accommodate many
different UI paradigms.
So whether you're using a
keyboard and mouse, or a multi
touch display, or the Siri
remote, or even the digital
crown on your Apple Watch, or
assistive technologies like
voiceover and switch control,
SwiftUI was designed to
accommodate all of these.
And it has great support for our
platform design conventions out
of the box.
We've brought together experts
from every platform to make sure
that when you use an element in
SwiftUI on a given device that
it looks and feels right at
home.
The result is a system where
your knowledge is transferrable
across devices.
Everything fits together in the
same way.
So even when you're working
with-- you're building support
for some specific piece of
hardware, say the Touch Bar on a
MacBook Pro or the digital crown
on an Apple Watch, or the Siri
remote, the tools for doing this
have a kind of consistency and
familiarity that makes them
really easy to pick up.
Now, on top of just general
design philosophy we also have a
number of elements that are in
common across-- SwiftUI across
all devices.
So for example, every platform
has the idea of a toggle
control.
You've got some kind of piece of
Boolean state that you want to
be able to toggle and you have a
label describing what you're
toggling.

And so even though our
expression of this control could
be very different on each
device-- it might be a switch or
a check box or a toggle button--
we can offer a single API that
describes this on any device.
SwiftUI also has a common layout
system.

So when you're using a stack or
a spacer or a padding, these
tools work the same on every
device.
And what that means is that once
you've learned to lay out an
application on one device,
you've learned how to lay out an
application on any.

We also have some more advanced
controls like picker for
example.

Picker picks one element from a
list of many and this control
expresses itself in a variety of
ways.
So on MacOS it might be a pop-up
button.

On iOS or WatchOS it might be
this wheel style picker.
And given how different they
are, you might not use them
completely interchangeably from
device to device.

But the one thing that's
constant is the relationship to
your data.

When you've adapted your model
to work with one of these
controls, you can easily
transplant that from device to
device.
Now we don't have time to go
over all of the different
elements available in SwiftUI so
you should check out the SwiftUI
essentials talk for more
information about that.
Now, does that mean that I can
really use SwiftUI to design a
single app that's going to work
great across all these devices?
Is it going to let me write code
to adapt seamlessly from a 4k
television all the way down to a
44 millimeter watch face?
Well of course not.
You know, there's no such thing
as a one size fits all app.
If we decided to just stick to
the common denominator between
all these devices, we'd be
missing out on the things that
make each device great.

And there's no magic abstraction
that can do that for you.
You have to decide what the
right design is for your app on
each device.
Now what SwiftUI can help you
with is you can share your skill
set and toolset that you've
learned building from one device
across many others.
And there are definitely going
to be opportunities to share
code along the way, just where
it makes sense.
And so we think it's kind of
important to think about this
less as write once and run
anywhere and more like learn
once and apply anywhere.
Now to put these principles into
practice, we need to build an
app.
But really it's more like we've
built four apps, one for each of
our platforms.
And the app that we've built is
called Landmarks.

The purpose of Landmarks is to
research and visit landmarks
throughout the country.

We definitely want to look at
photos and get visitor
information about these places.

I think it would be great to get
maps and directions to a
destination.

And if we're planning a trip,
marking favorites is a great
idea.

And when we think about bringing
this app to all of our devices,
we can tell ourselves a story
about how we think the app
belongs and fits on each one.
So for example, on AppleTV it's
a natural place to couch surf
for places to go.
And because it's a big screen
experience, that might be
something that you do with
family or friends or roommates.

And we definitely want to mark
favorites to research later.
And the Mac would be a great
place to do that research.
It's a good place to compare and
contrast info, maybe have some
more advanced sorting and
filtering controls, and really
read up on all the details.

On iPhone, we obviously want
quick information about each
landmark but since it's so
common to navigate with our
phones, we should also be able
to get driving directions as
well.
And iPhone of course is also a
phone so if we need to place a
phone call to call ahead, it's a
natural place to do it.
Finally on Apple Watch, that's
where we want to get at-a-glance
info about what's most important
to us.

And it's the perfect platform to
receive important notifications
when anything changes.

Now the cool thing is that the
iOS version of this application
is already available to you
today.
It's part of a new documentation
series to teach you how to view
SwiftUI.
You start from the very
beginning and you can build this
application up step by step.
It's already available for
download today and it's a great
way to learn how to build an iOS
app.
And so as a result, we're going
to be focusing more today on
bringing this application to
AppleTV, Mac, and Apple Watch.

And to start us off on that
journey, I'd like to hand it
over to my colleague Ada Turner
to talk to us about SwiftUI on
AppleTV.
Thanks Jeff.
Hi. My name is Ada Turner and
I'm really excited to talk to
you today about SwiftUI for
AppleTV.
Designing apps for the TV means
designing for the biggest,
boldest screen in the entire
home and that comes with some
challenges and considerations
unique to AppleTV.
Luckily, SwiftUI allows you to
create great experiences that
are optimized for the living
room using the same skill set
and toolset that you've learned
when developing for Apple's
other devices.

Today I'd like to focus on three
key points for designing great
experience on the biggest,
boldest screen.
TVOS is a 10 foot experience,
not a mobile experience.

People interact with your apps
using the Siri remote not a
touch screen or a mouse and
keyboard.
And it is especially important
for TVOS apps to have
streamlined navigation so people
can jump right into your app's
content.

Now, what is a 10 foot
experience?
It's this, not this.

Your apps should emphasize rich
and immersive experiences like
beautiful imagery or video as
opposed to accomplishing tasks
like taking notes or getting
directions.

When sharing SwiftUI code with
your AppleTV app from other
devices, carefully consider
which experiences make the most
sense when displayed on a large
screen viewed from across the
room with longer periods of use
and potentially more than one
viewer at a time.

Let's take a look at which
features we decided to support
on Landmarks for TV and which
ones we left on the cutting room
floor.
The easiest choice to make was
to include the gorgeous
photographs of the landmarks
which will look great on the big
screen.
Gathering in the living room to
pick out favorites together is
one of the key features of our
TVOS app so we can't forget
that.

And we'll also include basic
tourism information such as
hours of information and cost so
that people can make informed
decisions about where they want
to visit as they browse.

Now, although our data supports
it, we decided that we're not
going to include lengthy details
about the history of each
landmark as content like that
really isn't appropriate on the
TV.
We also decided not to include
advanced sorting and filtering
as features like that make a lot
more sense on the Mac or iPad.
And finally, although our data
includes geographical
coordinates, we decided not to
implement geofenced
notifications as traveling with
an actively running TVOS app is
a very rare use case.

[Laughter]
Next, let's talk about focus.
People interact with TVOS apps
using the Siri remote which is
optimized for effortlessly
swiping through your app's
interface.
It is critical that your entire
apps interface be intuitively
navigable using focus.
Luckily, many of SwiftUI's
standard interface elements such
as lists, buttons, text fields,
and toggles, all work seamlessly
on TVOS, adopting different
appearances and behaviors that
look great on the big screen and
interact using focus.

If you implement your own custom
controls, SwiftUI provides a
focusable view modifier that
allows you to control whether or
not your view can become focused
and execute a block of code when
your view gains or loses focus.
You can also use the on play
pause command and on exit
command view modifiers to
respond to people pressing the
play pause and menu buttons on
the Siri remote when your view
is focused.
Thank you.

Finally, let's dive into some
best navigation practices on
TVOS.
Long, vertically scrolling
tables of content with deeply
nested levels of navigation work
great on the Mac or iPhone, but
on TVOS people want an
effortless browsing experience
that emphasizes content.
Using SwiftUI's easily
composable stack views, list
views, and scroll views, we can
create an interface like this on
Landmarks for a TV with vertical
stacks of horizontally scrolling
shelves that really take
advantage of the widescreen
display on the TV and allow
people to browse between
different categories without
having to navigate between
different pages.

First, let's take a look at how
we might structure the top level
navigation of a SwiftUI app for
AppleTV.
Tab view is the primary means of
navigation for many TVOS apps.

It allows you to break your
app's content up into distinct
categories that are easy to
switch between and provides a
persistent indicator at the top
of each view that lets people
know where they are in your app.
Navigation view allows you to
nest pages of content and
optionally display a navigation
bar with a title or buttons.
I'd like to make a quick note on
structuring your app's top level
navigation on TVOS versus iOS.
On iOS if you use a tabbed view,
it will typically be the top
level view of your app and each
of its child views may be a
navigation view with your app's
content as the navigation view's
root view.

With this structure, when people
navigate deeper into your app's
content, the tab bar will remain
visible allowing people to
easily switch tabs at any time.
Here on photos the tab bar
remains visible on the bottom of
the screen after navigating to
the details page so that people
can easily switch tabs without
having to navigate backwards.
However, on TVOS if you use a
tab view you will actually want
to make the navigation view the
top level view of your app and
set its root view to the tab
view with your app's content as
the direct children of the tab
view.
With this structure, when people
navigate deeper into your app's
content, the top bar will
disappear and we want this
behavior because TVOS is all
about full screen experiences
that emphasize your app's
content.

Here on photos for TV the tab
bar disappears when we navigate
deeper into the album's details
so that people can focus on the
contents of the album.
SwiftUI views are highly
composable so it's super easy to
rearrange your app's navigation
structure for TVOS.

The nested relationships between
the tab view, navigation views,
and content views, are all
visually indicated by the
inherent structure of your code.
Now, let's put some of these
principles into practice and
tune up landmarks for TV.
First we will no longer be
needing this navigation bar
button title.
Next we'll get rid of this
navigation button and data
header label.
Let's see how this looks.

This is definitely an
improvement but we've got a ways
to go.

This long, vertically scrolling
list doesn't quite feel right on
TVOS so let's use a scroll view
with a nested HStack instead of
a list.
And let's display all of the
landmarks within a category
inside of a row.
Let's take a closer look at the
row.
It's very similar to category
landmarks with the addition of a
VStack containing a header label
and an HStack wrapping the four
each landmarks.

One thing to note here is that
instead of a plain text view,
I'm using a custom view called
landmark card as the label for
the navigation button and I'm
sharing this view directly with
the iOS app.
Let's give this a run.
This is starting to feel a lot
better.
By changing only a few lines of
code, I now have a nice, big
inviting buttons with images and
a vertically scrolling list that
really takes advantage of the
wide screen.
One thing I'd like to point out
here is that while we're still
using the exact same navigation
button view in landmarks row,
its appearance has changed.

The chevron on the right hand
side of the view is gone and the
background is different.

This is because navigation
button is no longer being
displayed in the list view and
has automatically adapted its
appearance.
Now, while the horizontally
scrolling content looks great on
the big screen, it might be a
little too horizontal.

Let's vertically stack the
categories by changing the main
view's HStack to a VStack.

And adding a nested scroll view
around the row's HStack.
Let's give this a run.

Ah, this is feeling really,
really great.
It's super easy to browse
between different categories and
browse the landmarks within each
category.

Finally, let's take a look at
the details page.
Well, this beautiful edge to
edge photograph of the landmark
would be looking pretty nice if
it wasn't obscured by all of
this high density text.
Let's see what we can do to make
improvements for AppleTV.

So let's take a look at the
details view.
It's a pretty simple view.

We have a background displaying
a photo of the landmark, a
favorites button, and some
historic details.
Let's try displaying tourism
details.

Try one last time.
Ah, that's looking so much
better.

Only the most relevant details
are being displayed with nice
large fonts that are easy to
read from across the room.
We can mark a few landmarks as
favorited for when we do more
detailed research on landmarks
for MacOS.
Now, back to you Jeff.

Thanks Ada.
I love that Ada was able to take
a pretty standard list-based UI
and really make it feel at home
on AppleTV just by rearranging a
couple of pieces that she
already had.
I think that really shows how
powerful this framework is.
So now let's turn our attention
to MacOS.

Now there's a lot that goes into
making a great Mac app and I
could probably fill the whole
hour if we had it, but I'm going
to focus on a few key points
that SwiftUI can really help you
with-- high information density,
multi windowing support,
keyboard shortcuts, and support
for the MacBook Pro Touch Bar.
Let's start with high
information density.

We generally have a lot of
screen real estate to work with
on the Mac and so we can use
that to provide more information
at a glance.
That can make it easier to make
more, to make better decisions
and make comparisons if you have
all that information all in one
place.
And because we have a precision
pointing device on the Mac, we
can tolerate smaller click
targets and denser controls.
Now that doesn't mean that your
app should look like an airplane
cockpit, but it does mean that
you can provide more
functionality in one place and
leave more room for your
content.

And the Mac is a great place to
read lots of text content if you
have text content.

So app sessions are often longer
on the Mac and you're usually
using it seated so it's very
comfortable to just scroll
through some text and read it.
Now SwiftUI automatically
adjusts the spacing and paddings
between elements to be
appropriate for the Mac.

And you can use the control size
modifier to access the small and
mini sized controls that we have
available on the MacOS system.
And that might be great if you
want to make an entire inspector
use small controls.
Next multi windowing.
You know multiple windows have
been just a staple of the MacUI
for decades, and people love
using multiple windows.

They love using multiple windows
to compare content across
windows side by side.

It's often nice to pull a single
item out into its own window so
you can focus on it in detail.

And many people love organizing
their windows spatially across
their desktop and spaces.

And these are all capabilities
that you unlock if you support
multi windowing.

And SwiftUI makes this super
easy.
I'll show you an example of that
in a little bit.
Next, keyboard shortcuts.
Keyboard shortcuts are an
essential part of a MacUI.
Mac users and especially power
users love using keyboard
shortcuts to access common
actions and just fly through
your app's navigation.

And supporting keyboard
shortcuts in SwiftUI is really
easy and I'm going to show you
an example.
So let's say we have a tab view.
We've got three tabs for
explore, hikes, and tours, and
what we want to do is bind each
of these tabs to command one,
two, and three, so that we can
switch between them really
quickly.

Now when we want to set up a
keyboard shortcut on the Mac,
the first place that we go is
actually the Mac menu bar.
We like to put keyboard
shortcuts into the Mac menu bar
because it makes them more
discoverable and it ensures that
whatever actions we're hooking
up here are also accessible if
you're using just a mouse.
Now you could do this in code.

I've gone ahead and set it up in
my storyboard.
And then what I've done is
defined some commands for each
of these keyboard shortcuts.
A command is just a name for a
command that can be sent through
the SwiftUI hierarchy and we can
use them to wrap the selectors
sent by each of these menu
items.
Putting it all together, all we
have to do is use the on command
modifier attached to the view
that we want to recognize
commands on.
In this case we pass in the
command that we just defined a
moment ago, as what was a block
of code to run when the command
occurs.

So when we use one of these
commands, the selected tab
variable updates, the tab view
notices and updates itself as
well.
If you want to know more about
recognizing keyboard shortcuts
and other system level
integrations like this you
should check out the integrating
SwiftUI talk from this year.
Finally, the Touch Bar.

The Touch Bar is another great
way to accelerate common actions
on your Mac.

It brings the most common and
contextual actions right at your
fingertips.

And supporting the Touch Bar in
SwiftUI is easier than ever.
I'll show you an example.

We define a Touch Bar in code
and then just like we're
populating a list or a stack, we
just put the elements that we
want in the Touch Bar one by
one.

And when we want to attach this
to a view, we'll just use the
dot Touch Bar modifier, passing
in the Touch Bar that we're just
defined.
And it's that easy.

Whenever this view is the
focused view or the nearest
ancestor of the focused view,
these controls will appear in
the Touch Bar hardware.
Now let's go back to our demo so
we can put some of these into
practice for Landmarks for
MacOS.

Okay here we are in Xcode.
Let's just build and run
Landmarks for MacOS so we can
see where we're starting.
Okay, we have a fairly standard
master detail view here where
we've got a list of landmarks on
the left and the details on the
right.

We've also added some filtering
controls so that we can go
filter down by category or we
can choose to see only our
favorites.
Now the really neat thing is
that this list I've got here on
the left side is actually
something that I shared
completely with iOS.
And that was great.
It gave me a really big head
start to making this app.
And I didn't have to do any
adaptation.

I didn't have to adapt it to a
new data source or delegate
protocol or anything like that.

I just got it for free.
But I do think that this list
could look better on the Mac.

I wish I could see more elements
in my scroll view at once and
I'd love to have more details in
each row.
Let's start by taking a look at
how this is defined.

In our landmark list we've gone
ahead and actually defined a Mac
landmark list that wraps this
landmark list which is a common
element that I discussed
earlier.

Structuring our project like
this is really handy because it
means that I can still mostly
share the implementation of this
list but it gives me a place to
put my Mac specific
customizations.
Let's follow this to look at how
this is defined.

We have some filter criteria
that just describes the
configuration of our filter
controls that we looked at
earlier.
We have a binding to the
selected landmarks the list-- so
that the list can show and
modify it.

And we have some user data so
that we know what landmarks are
favorited.

And the list is pretty simple.
You've probably seen this a
number of times already.

We have a list we use for each
to iterate over all of our
landmarks to display.

And then we create a landmark
row for each one.
And this is a hard-coded type
here.
It's just, this is the type of
row that we're using right now.

Now we could start doing
something like poundif [assumed
spelling] to exchange what
landmark where we're using on
each OS but I really don't want
to do this as a hack.

I want to build a tool that I
can reuse.
And so let me show you how I'm
going to do that.
So I'm going to redefine this
list to be generic over the type
of landmark row that we're going
to use.
And then I'm going to add a
property which is a closure from
the landmark to the row type
that we've just defined as a
generic type.
And then instead of using a
hard-coded type here I'm going
to delegate the creation of the
row to my block.
Now, to adapt that in my Mac
landmark list, all I have to do
is update my type definition
here, add the closure that I
just described, the row
provider, and return a row type.
Luckily like any good TV demo I
had one baking in the oven all
along so we'll just use that
one.

Let's take a look at how that
looks now.
Now this is a lot better.

My rows are a little bit more
compact.
I've added some more details to
each one and I can even see at a
glance which ones are favorited,
and that's really nice.

And the great thing here is that
my list implementation is still
completely shared.

So if I still had-- if I had
like really advanced filtering,
sorting, or grouping logic, or
if it was especially fancy,
let's say I had some
asynchronous work that was going
to a database or to the
internet, you know personally I
only want to write that code
once.
And now we can and we don't have
to compromise on our design to
do it.
The next thing that I'd love to
be able to do is to double click
one of these rows to pop it out
into its own window.
And that's also really easy.

I'm going to show you how.
The first thing that we need to
do is create a window and on the
Mac, even when we're defining
our views with SwiftUI, we use
AppKit to define our windows.

Now I could do this in my
storyboard but the code is
really short so I'm just going
to show it to you.
We have a window controller and
then I've defined a convenience
initializer that takes a SwiftUI
view, puts it into a hosting
controller, and then creates a
window around that hosting
controller.
I've also written a little bit
of convenience code here that
just keeps track of which
windows exist per landmark
already so that if I double
click on a row that already has
a window, it'll bring the
existing window front instead of
creating a new one every time.
Let's go back to our list and
add this integration.
So, detail-- let's add a quick
convenience method--
shared-- to show a window for a
given landmark.
And then to attach it to my row,
I can just add a tap action with
a count of two because I only
want it to recognize double
clicks, and then in this tap
action I'll call my show detail
for landmark method.

Now, when I double click on my
rows, I can pull them out into
their own windows and I can put
them side by side, arrange them
however I'd like.
And because these are still
AppKit windows I can use all of
the great windowing features
that are built in.

So if I like tabs I can merge
them into tabs and it's just
like that.

I get that completely for free
which is really great.
And with that, I think that the
Mac version of this app is
starting to look pretty good so
I'm going to go ahead and go
back to our slides.
So now that we've seen SwiftUI
on AppleTV and Mac, it's time to
turn our attention to Apple
Watch.

You know SwiftUI is the first
truly native framework for
building apps on Apple Watch and
I think it's going to really
broaden our horizons for what's
possible.

And to walk us through some of
those possibilities, I'd like to
hand it over to my colleague
Meghna.
Thank you.

Thanks Jeff.
With SwiftUI and all the amazing
things you've learned so far you
are bound to be on track to
build an app that provides an
awesome experience on all
devices.
Hi, I'm Meghna and now I'm going
to talk to you about bringing
this great experience to your
Apple Watch App.

While your experience may be
rooted in your application,
building for WatchOS means so
much more.
Complications, Siri shortcuts,
and notifications all contribute
to showing the most timely
information right on your Apple
Watch face.

Apple Watch is all about showing
the right information at the
right time.

For the purposes of this talk,
I'm going to focus on the app
and notifications.

We'll start with talking about
how SwiftUI allows you to
display elements and lay out
your Apps UI like never before.
But first things first.
A good rule while building an
Apple Watch experience is to aim
for the primary information or
the most critical action to be
available within two or three
taps.
While designing this experience,
the aim isn't to shrink down
your iPhone app but to bring the
most timely and relevant actions
to the context of your wrist.
With that, let's dive into some
SwiftUI simple concepts.

If you have content that exceeds
the bounds of a full screen, you
can wrap it in a SwiftUI scroll
view.
SwiftUI also gives you this
great new digital crown rotation
API which lets you completely
control rotation and haptics.
This API also opens the door to
using the digital crown in all
new ways to modify interface
elements.

This is something that was never
possible before.
You're also probably familiar
with groups in WatchKit.
SwiftUI now gives you much more
powerful ways to organize your
content with horizontal and
vertical stacks.
Tabulating information has never
been easier than with lists and
with list sections.
Lastly, identifying what your
users care about the most on
your Apple Watch App will help
you decide what kind of data to
surface.
With the views and controls
provided by SwiftUI, you can
easily build an interface that
conveys the most crucial
information first.

Notifications are a great way to
give timely updates, however,
too much information or content
that isn't useful may lead
people to turn them off for your
app.

SwiftUI gives you the ability to
easily provide intuitive and
beneficial controls so people
can respond from within your app
and not have to dismiss the
notification.

Making your notifications
actionable as possible, you can
allow people to quickly respond.

When you send your notification
can be just as important as what
you send in it.

Try to use what you know about
how someone uses your app and
with that information you can
send the most timely information
at the most appropriate time.
With these powerful new SwiftUI
concepts and a better
understanding of what makes a
great Apple Watch experience,
let's take a look at the
landmarks app where we put some
of these concepts to use.

Using the app you've built with
SwiftUI for all the other
devices you're going to have a
functional Apple Watch App.
However, it may not be the best
Apple Watch experience.

I'm going to show you how, with
a few tweaks and updates, you're
going to be able to bring this
app more in line with the
context of the wrist.
Well the first thing you see
here is that we've built a
landmarks list.
For the watch landmarks, we've
gone ahead and customized the
details cell.
We've included an image for some
context.
We've included some tool details
and we've also added some
contact capabilities.
Now some of these things like
the contact capabilities don't
add too much value to say, an
AppleTV app but they work great
inside an Apple Watch App.

But that was still way too much
content to scroll so what we
decided to do is to narrow it
down to just our favorites.
To do that we created a simple
Swift filter.

Since we've narrowed this data
down, we also wanted users to
have an option to see all the
landmarks if they chose to.
That was possible with adding
this button.

This button simply toggles the
state between showing all and
showing favorites based on the
view that you're in.
SwiftUI gives you this unique
ability to pick the pieces that
interest you for your app and
compose the views that work best
for your interface.

We wanted to be able to focus on
each cell more when we scroll.
With SwiftUI we were able to do
that with the carousel list
style.
This list style is great when
you have a fewer number of cells
or when you have cells with
interactive controls.

Here our cell has buttons for
contacting, for making a phone
call, for adding or removing the
landmark from favorites, and
having some navigation
capabilities.

Lastly, notifications.
For the landmarks app we wanted
to notify you when a new tour
has been added.
We wanted to add some images so
you can decide if you're
interested in this tour.
And also give you the ability to
book it from within the
notification.
Using the power of Swift, you
not only have the textual
information but you also have
this gorgeous, rich animation
moving the images.

Instead of just talking to you
about it I'm going to show you
how we built this.

So what you see here is that
I've created a structure for a
new tour notification.

Now I've already gone ahead and
hooked this notification up to
my notification controller which
means that whatever is in this
body is what you see inside the
notification after I run this
scheme.
This struct [phonetic] takes in
a landmark as a parameter which
is what the notification will
ideally pass to it.
Now let's go ahead and add some
text.
Okay so what we've done here is
that we've created a stack that
includes some textual
information.
The only reason I have a stack
here is because I'm going to add
some more data inside this.
In here we have decided a struct
called slideshow which takes in
an array of strings.
These strings are image names.

We have a variable which is
called the current index which
is essentially just to track
which image you're on at this
point.
Tour image is a custom
struct that I've created
which is a view.
It takes in an image name that
aligns the image correctly
inside my app.
Let's see how this looks in the
previews so far.
Now, the next thing I want to be
able to add here is an ID for an
image.
That way when we animate this we
will have a proper track of what
view needs to be inserted and
what view needs to be removed.
At this point it looks like--
okay we have our text here,
great-- at this point it looks
like we can go ahead and add
this slideshow struct inside our
notifications body.
All right so once this updates
we should be able to see this
view here.
This looks great.

Now like we talked about here,
we should be able to support
multiple images inside this
struct.
For that, we would need to
calculate the next index.

Let's go ahead and do that.
Now in here I'm simply
calculating the next index and
I'm updating the current index.
What I also want to do is
animate this change.

With a simple animation, every
time my current index is updated
it will have some fluid string
animation which looks pretty
good.
Now, we've created this but we
haven't actually hooked it up to
anything.
Inside our ZStack ideally what
we'd want is that after a
particular interval in time we'd
want the image to change and
move on to the next image.
So I created an extension on a
view which has a view modifier.

Show next image is a simple view
extension which essentially
invokes a timer that after every
two seconds switches on to the
next image index.
Now the last thing I want to add
here is this gorgeous slide
transition we saw, which is this
easy command right here.

Okay, let's see how this looks.
Okay so we have these images
scrolling through.

We have some actions that we had
hooked up to the notification
controller before.

As you can see-- [applause]
thank you.
Like you see, with very few
changes we were able to create
this gorgeous, rich notification
which in WatchOS was never a
possibility before.
With that, let's go back to
Jeff.
All right, thank you Meghna.

I think it's so cool to see
something so rich and
interactive appearing just in
the context of a notification.
I think SwiftUI is going to
really broaden the horizons for
what's possible on WatchOS.
Now this has been just a
whirlwind tour so let's kind of
revisit and sum up what we've
learned today.
The first thing is that when
we're thinking about bringing an
application to a given device,
take a design first approach.

This isn't about saying that
I've got this code and I'm going
to try and get it working over
here.
It's thinking about what's the
right expression for my app on
this device and working
backwards from there.
But, you can share some code
sometimes.
For example, we didn't really
call it out but every demo that
you saw today is effortlessly
sharing the model code.
The model code has been compiled
into each target identically.
And you can share view code, you
just have to use good judgment
about when you do it.
And SwiftUI can help you along
the way by making it really easy
to re-factor out small, reusable
components that make more sense
to reuse across devices.

And finally, we're not here to
write once and run anywhere.
The real power is in your
knowledge.
When you learn once, you can
apply that to any device and I
think that's really powerful.
As always, this talk lives
online.

There you can see the video
replay and get associated
resources and I want to thank
you for your time.
We cannot wait to see what you
build with SwiftUI.

Looking for something specific? Enter a topic above and jump straight to the good stuff.