WWDC2018 Session 211

Transcript

[ Music ]
[ Applause ]
>> Hi, everybody.
My name is Ari Weinstein, and
I'm really excited to be here
along with Willem Mattelaer to
tell you about Siri Shortcuts.
So, two years ago, we announced
the first version of SiriKit,
which enables your apps to work
with Siri, and it has great
domain-specific knowledge for
things like sending messages,
requesting rides, making
payments, and more.
But we know that you want to do
even more with SiriKit, and so
that's why, this year, we're so
excited to announce Shortcuts.
This central idea behind
Shortcuts is that it lets you
expose the key capabilities of
your app to Siri, and this is
really great, because it enables
people to use the features of
your apps in new ways and in new
places.
And it's a really powerful way
to engage your users.
So, exposing a shortcut opens up
a ton of new possibilities for
how people can use your apps, so
let's explore all of the places
where Shortcuts can be used.
Shortcuts takes Siri's
suggestions to the next level by
surfacing what you want to do
next, not just with your apps,
but inside of your apps, and it
does it by surfacing them in
search at just the right time.
And Siri can suggest shortcuts
on the Watch, so you can use
them right from your wrist on
the Siri Watch Face.
When Siri is confident that it's
the exact right time for a
Shortcut, it will be surfaced on
the lock screen.
And, when you tap on a shortcut,
you can use it right in line
with a rich custom UI specific
to that app.
And you can also add shortcuts
to Siri, so you can use them
with your voice just by asking
Siri.
And in Siri you'll see the same
custom UI that you see in search
and on the lock screen.
And apps can provide a great
voice experience in Siri by
providing custom response dialog
that Siri will read out loud to
tell you things like how long it
will take for your coffee to be
ready.
So, when the user adds a
shortcut to Siri, they get to
pick a custom personal phrase,
so the user chooses what to say
to Siri to invoke your shortcut.
And, as a developer, you get to
suggest what phrase to use, so,
in this case, a suggestion is
"coffee time."
And, once a shortcut has been
added to Siri, it works across
all of your iOS devices, and on
Apple Watch, and even on
HomePod.
So, we also have the new
Shortcuts app, and with the new
Shortcuts app, anyone can build
their own shortcuts, and you do
it just by dragging and dropping
a series of steps together.
And those steps can even include
the shortcuts exposed by your
app.
So, today, we're going to talk
about how to adopt shortcuts for
your apps, and then we'll talk
about how to optimize your
shortcuts for great suggestions.
And we'll also cover some
privacy considerations that are
important to keep in mind, and
we'll talk about how to make
great shortcuts for media
playback.
So, first, we'll talk about how
to adopt the new Shortcut's
APIs.
There were three steps for
creating a shortcut, and the
first step is to define your
shortcut.
That means you have to decide
what you want to expose as a
shortcut and define each one so
Siri knows everything that your
app can do.
Next, you'll need to donate your
new shortcut.
That means you need to tell the
system every time the user does
something in your app that you
expose a shortcut for, which
will let Siri learn when and
where is the right time to
suggest your shortcut.
And the third step is to handle
your shortcut.
That means, when the user wants
to go and use your shortcut in
Siri, on the lock screen, in
search, you need to be ready for
your app or app extension to be
invoked and be handed the
shortcut to handle.
So, before you define shortcuts,
you'll need to decide what
exactly it is that you want to
expose.
And you should start by thinking
through what are the most
important things that people
like to do with your apps?
Because those are the things
that you might want to consider
exposing shortcuts for.
So, every shortcut that you
expose should accelerate the
user, to perform a key function
of your app.
That means it should take
something that the user already
wanted to do with your app and
help them do it even faster.
The acceleration that you offer
should be substantial, so you
shouldn't just expose a shortcut
that does about the same thing
as opening your app normally.
If you expose a shortcut that
doesn't provide very much
acceleration to the user, it
won't be suggested as
frequently.
And, next, every shortcut that
you expose should be of
persistent interest to the user,
so that means it should be
something that the user might
want to do multiple times.
It's not a good idea to expose a
shortcut for something that the
user might only want to use once
or twice.
And you should also expose only
shortcuts that are executable at
any time, because you can't rely
on the user being in some
particular state before your
shortcut will be ready for use.
So, once you've decided what
shortcuts to expose, you're
ready to check out the
shortcuts' APIs.
There were two APIs that we
support for adopting shortcuts.
The first is NSUserActivity.
NSUserActivity is a lightweight
way to represent the state of
your app, and it integrates with
other Apple features like
Spotlight and Handoff.
And the second is intents.
Intents are a way of
representing, in detail, a type
of action that your app can
perform, and Siri includes a
bunch of great built-in intents
that support a range of
capabilities that apps can use
to integrate with Siri.
And, this year, we're
introducing something really
cool, which is the ability for
you to define your own custom
intents for use with Shortcuts.
So, for every shortcut you
expose, you'll need to decide
whether it should be an
NSUserActivity or an intent.
So, let's talk about how to make
that decision.
Now, NSUserActivity is a great
choice for building a shortcut.
If you're just building a simple
shortcut that opens something in
your app, or if you're exposing
a shortcut for something that
you already index in Spotlight
search, or that you already
offer in NSUserActivity for, for
example, for Handoff.
But for the best Shortcuts
experience, you'll want to adopt
intents, and intents-based
shortcuts are really cool,
because they can run inline
without launching your app.
And they can include custom
voice responses and custom UIs
like we saw earlier.
And they can also include
granular parameter predictions,
which Willem tell you a little
bit about later.
So, once you've decided how to
adopt, you're ready to dive into
the implementation, so let's do
that now.
First, let's go over how to
adopt shortcuts with
NSUserActivity, and the first
step is to define your shortcut.
For NSUserActivity, that means
you need to declare a
UserActivityType in your app's
Info.plist file to register your
activity type with the system.
Next, you need to donate your
shortcut.
For NSUserActivity, that means
every time the user is looking
at the screen in your app that
you want to provide a shortcut
to, you should make an
NSUserActivity object available.
So, there's one key new thing
here, which is the
isEligibleForPrediction flag.
Setting this on any user
activity turns it into a
shortcut, and what's really cool
is if you have an existing user
activity in your app, you just
have to set this to true and
that user activity will become a
shortcut automatically.
Now, note that the
isEligibleForSearch flag has to
be true in order for
isEligibleForPrediction to have
an effect.
And, by the way, you might also
want to consider the
isEligibleForHandoff flag, which
defaults to true.
So, by default, all of your user
activities will be able to be
handed off between devices.
Now, when you're creating your
user activity, you want to make
sure to include all of the
information in your user info
dictionary that you'll need to
restore the activity later on.
And the last step is to mark
your activity current by
attaching it to a UI
viewController or a UI responder
object that's onscreen.
Now, the last step is to handle
your shortcut, once you've
defined and donated it.
And every time the user uses an
NSUserActivity from your app, it
will be opened in your app.
And so you need to handle it by
implementing the app delegate
method for handling
NSUserActivity, which is called
continueUserActivity.
So, all you have to do is
implement this method, check if
the activity type matches the
one that you registered, and, if
it does, then you want to
restore the state of your app to
what it was when the user
activity was saved.
So, that's everything you need
to do to get Siri to start
suggesting shortcuts for your
apps with NSUserActivity.
Now, let's talk about how to
expose Shortcuts through
intents.
The first step, again, is to
define your shortcut.
And so with intents, you'll need
to start by deciding what type
of intent you'd like to adopt.
And, as you know, Siri includes
many great built-in intents,
like for messaging, workouts,
lists, and more.
And now we're introducing the
ability to define custom intents
in Xcode for Shortcuts.
And so if the shortcut that you
want to build corresponds to one
of the default built-in SiriKit
intents, then you should adopt
that.
But, otherwise, you can define
your own.
And whether you want to define
your own or adopt an existing
one to customize it, you want to
get started by creating an
intent definition file in Xcode.
So, believe it or not, in my
spare time, I've been working
with a couple friends on a new
app, and it's a soup delivery
app, and it's called Soup Chef.
It's the easiest way to order
soup, and I'm really excited
about the potential of hooking
it up to Siri.
So, let's step through how to
use the new Intent Editor to
build an intent for Soup Chef.
I'm going to start by going to
File, New File in Xcode, and
I'll choose the SiriKit Intent
Definition File type.
And then I'll see the new Intent
Editor.
So, let's get started by
clicking the plus button in the
bottom left.
Next, I want to give my intent a
name.
And, so in this case, I'm making
an intent for ordering a soup,
so I'm going to call it
OrderSoup.
Then I want to fill out my
intent's metadata.
So, let's look at that one step
at a time.
The first piece of metadata is
category and defining a category
helps Siri know how to talk
about your intent and how to
display it in the UI.
So, for example, in this case,
I'm choosing the Order category,
and when I choose Order, Siri
will say something like, "Okay,
I ordered it," when I use it
with Siri.
And it'll display a button
confirmation title like Order.
So, we offer several different
categories, and you should
choose the one that matches your
intent's purpose the most
closely.
Next, you want to fill out your
intent's title and description,
and that will be used in all the
places where people can discover
which shortcuts your app
supports.
And then there's the User
confirmation required checkbox,
which determines whether or not
we'll ask the user for a
confirmation before using your
shortcut.
So, Siri might say something
like, "Are you ready to order
with Soup Chef?"
That's really great for my app,
because I want to make sure that
people aren't accidentally
ordering soup [laughs].
So, then, you'll see the intense
parameters.
And these define all of the
parameters that are passed to
your shortcut.
For example, in my case, I have
two parameters.
They are the list of items being
ordered and the location to
deliver to.
Now, parameters support a short
list of types, and those types
include things like string,
number, person, and location.
But if you're building a
parameter that represents an
object that's in your app that's
not on the short list of types
then you can choose the custom
type.
Once you've defined your
parameters, you'll want to look
at shortcut types.
These define all of the types of
shortcuts that you'd like to be
suggested to the user.
Each type includes a particular
combination of parameters that
will be predicted, and formats
for how to display the title and
subtitle of each one, filling in
the values for your parameters.
So, if your shortcut can't be
performed in the background
because it needs to launch your
app when you use it, you should
uncheck the Supports background
execution checkbox.
Now, in some cases, one intent
may have multiple shortcut
types, where some support
background execution and some
don't.
Now, in the case of Soup Chef,
that's especially relevant,
because we can support
background execution when both
the items and delivery location
are predicted, because we have
all we need to place an order.
But if we add a shortcut type
that only includes delivery
location, Siri may predict that,
and we won't actually have
enough information to place an
order.
So, we'll need our app to open
to ask the user what location to
deliver to, and, in that case,
we'll want to not support
background execution for that
shortcut type.
Now, you should specify shortcut
types for every variation of
your shortcut that you think
will be useful so that Siri can
make the best predictions.
And, for the best experience,
you should-- on all the shortcut
types, you can-- support
background execution.
Shortcut types that support
background execution provide
more acceleration to the user,
and so they'll actually be
suggested more frequently.
You can provide up to 16
shortcut types for every intent
that you define.
Now, once your intent is
defined, Xcode will
automatically code generate an
intent class and an intent
handling protocol.
In my case, we've generated the
OrderSoupIntent class and an
OrderSoupIntentHandling protocol
with properties that correspond
to what I just defined in my
intent definition file.
Because Xcode is doing code
generation, it's really
important to consider in which
targets Xcode is doing this code
generation, because you don't
want to end up with duplicate
instances of the same classes
that conflict with each other.
So, let's look at the targets in
the target membership section of
the inspector on my intent
definition file.
Your intent definition file
should be included in every
target in which your intent is
used, so you should check the
box under Target Membership.
But you'll want to make sure
that if you have a framework,
you don't do code generation in
multiple targets that are
included from each other.
So, if you have a framework, set
the target membership to only
generate intent classes for that
framework by choosing intent
classes and choosing no
generated classes for every
other target.
But if you don't have any
frameworks in your app because
you haven't separated your app
into frameworks yet, you should
check the target for every
single target.
And that's how you define custom
intents in Xcode.
Once you've defined your custom
intent, it's really easy to
donate it.
All you have to do is
instantiate your intent object
and then populate its parameters
and create and donate an
INInteraction object.
Make sure to do this every time
the user performs the equivalent
of your shortcut in your app.
In this case, every time the
user orders soup, I want to
donate this intent, because
that's going to help Siri learn
when is the best time to predict
it?
So, all that's left, now that
we've defined our custom intent,
is to handle it.
And, just like with
NSUserActivity, you should
implement the
continueUserActivity method in
your app delegate in order to
handle your intent.
So, when an intent is opened in
your app, it's passed in as an
NSUserActivity object, whose
activity type is the name of the
intent class that you generated
earlier.
In this case, it's
OrderSoupIntent.
But if you only implement
continueUserActivity, your
shortcut will open your app
every time.
It won't run in the background,
or work inline in Siri, or
support things like custom voice
responses.
So, for the best experience, you
want to create an extension to
handle your shortcut in the
background.
And to do that, create a new
target in your Xcode project and
choose the Intents Extension
template.
Make your intent handler conform
to the intent handling protocol.
In this case, it's
OrderSoupIntent handling and
then implement these methods,
which are confirm and handle.
Now, note that unlike
traditional SiriKit, you don't
need to implement any resolve
methods, because your intent is
ready to go without any
customization needed or any
follow-ups from the user.
So, in confirm, you should check
all of the values of the
properties of your intent to
make sure that they're valid.
And, if they're not, you should
return an error code if you
don't think you'll be able to
handle that intent.
And then you should handle,
actually perform your shortcut.
So, in this case, that means
actually placing an order for
the soup.
And then you return a response
object that indicates the
outcome, such as success.
Again, you should implement an
intents extension for every
shortcut that can run in the
background, because then they'll
run right in line inside of
Siri, on the lock screen, in
search, in the Shortcuts app,
and on the Siri Watch Face,
without having to launch your
app.
The most valuable shortcuts are
the ones that run in the
background, but you can also
build a lot of great other
shortcuts.
And keep in mind that, even if
you implement an intents
extension, you should always
implement continueUserActivity,
because the user will have the
opportunity to open the shortcut
in your app from Siri, for
example, by tapping on the card
in Siri that shows your apps'
custom UI.
So, there's one more thing that
I want to tell you about, which
is INRelevantShortcut.
Now, INRelevantShortcut is the
way to expose shortcuts to the
Siri Watch Face, and you do it
just by providing
INRelevantShortcut objects that
include your intents or user
activities.
You can, optionally, include
relevance information in your
relevant shortcuts, which is a
hint to the Siri Watch Face as
to when your shortcuts will be
relevant and when's the best
time to show your shortcut?
Now, the really cool thing about
INRelevantShortcut is that it
works even if you don't have a
Watch app.
So, you can actually expose
relevant shortcuts from your iOS
apps, and if they run in the
background, they'll appear right
on the Siri Watch Face.
Okay, now that we've explored
all the ways that Shortcuts can
be used and how to adopt the
APIs, I'm going to turn it over
to my colleague Willem who's
going to give you a great demo
of how to adopt shortcuts in
Xcode.
Willem?
[ Applause ]
>> Thanks, Ari.
I'm so excited to be the first
one to demo adopting Shortcuts.
Before I dive into Xcode, let me
show you the app we've been
working on.
As Ari mentioned, we've been
working on a soup-ordering app
called Soup Chef.
Let me show it to you.
So, this is Soup Chef.
When I launch the app, I'm
presented with my order history.
Since I haven't ordered anything
yet, this is still empty.
I can place a new order by
tapping the plus button.
This presents me with the soup
menu, where you can see the
available soups I can order.
Let's order a tomato soup.
Next, I can specify the quantity
and options for my soup.
I'll order a single tomato soup
with red pepper, and when I'm
ready to order, I tap the Place
Order button.
I'm brought back to the order
history where you can now see
the order that I just placed.
I can tap the order to see more
details about a specific order.
This view has an associated user
activity.
I think it would be pretty cool
to suggest this to our users,
since our users like to
reminisce about the good soups
they've ordered in the past
[laughter].
And it would be great if this
could be suggested to them.
So, let's go to Xcode and see
how we can do that.
Here, I'm looking at the
viewController for the order
detail view.
I'm creating a user activity,
and I'm setting the
requiredUserInfoKeys.
I'm also making sure that it's
EligibleForSearch.
For it to be suggested, I also
need to make it eligible for
prediction.
And that's it.
Let's try it out.
First, I need to make sure that
I donate the user activity, so
I'll go back to the view.
That should be enough.
Now we want to make sure that
the donation actually happened,
and, to do that, we added two
new developer settings that make
it super easy to see a recent
donations in search and on the
lock screen.
To enable it, I go to Settings,
and I scroll down to the
developer section.
At the bottom, there are two new
toggles, Display Recent
Shortcuts and Display Donations
on Lock Screen.
Let's enable both.
I can now go back to the home
screen and pull down to go to
search, and I see the donation
that I just did.
Great.
[ Applause ]
I can tap it, and the app is
launched with that user
activity, and I'm back to the
order that I was just donated.
Great. So, this is pretty good,
but I think we can do a lot
more.
Since the main capability of our
app is ordering soup, it would
be great if this could be
suggested to our users.
And I want users to be able to
do that without having to launch
the app.
So, I'll implement it using an
intent.
There isn't a built-in soup
order intent, but now in iOS 12,
I can create a custom intent, so
I'll do that.
And to start by creating an
intent definition file, I'll go
to File, View.
File and select the SiriKit and
then definition file.
Click Next.
Now I can give it a name.
I'll keep it to Intents, and
I'll put it in the Resources
group.
All right, and I'm ready.
I click Create.
I'm presented with our intent
definition file and our new
Intent Editor.
Before I add the intent, I'll
make sure to include the intent
definition file in the right
targets.
As Ari said, we need to add it
to all the targets where the
intents are used.
So, I'll add it to our shared
framework, and, since we're
using a shared framework, I
don't want it to generate go for
app target.
So, in the dropdown, next to the
app target, I'll select No
generated classes.
Now that that's done, we're
ready to add our intent.
I'll click the plus button in
the lower left corner and select
New Intent.
I'll give it a name OrderSoup.
Next, I'll select the category.
In this case, it's an order
intent.
Fill out the title, OrderSoup,
and the description, Order a
soup from Soup Chef.
Since this involves a real-world
transaction, I want to use it to
confirm this order before
placing it, so I'll select User
confirmation required.
Next, let's define the
parameters.
I'm going to define three
parameters, one for the soup,
one for the quantity, and one
for the options that the user
selects.
I'll start with soup.
I click the plus button in the
parameter section and fill out
the name, soup.
Since soup is a custom object of
our app, I'm going to select the
custom type.
Next, I'll add quantity.
I click plus again, fill out the
name, and this is going to be an
integer.
Next, options.
Again, options is a custom
object of our app, so I'll use
the custom type.
And since the user can select
multiple options, I'll also
check the array checkbox.
Finally, we need to define the
shortcut types.
At this point, I'm just going to
define a single shortcut type
that contains all the
parameters.
I'll click the plus button in
the shortcut type section and
select the parameters I want to
include in the shortcut type, so
I'll select soup, quantity and
options.
When I'm ready, I click the Add
Shortcut Type button.
I fill out the title Order, and
then I'm going to insert the
quantity and the soup with
options, and I'll leave the
subtitle empty, because I've
already conveyed all the
information I need to in the
title.
I'll also leave Support
background execution checked,
because I want the user to run
this intent in the background.
So, we just defined our first
intent.
Let's start using it.
I'll start by adding two helper
methods to our order object to
make it easier to convert
between it and the intent.
I'll go to the order class and,
at the bottom, I'll add an order
extension.
It contains a computer variable
that returns an intent.
In it, I create the intent.
I set the soup quantity and
options, and I return the
intent.
Extension also defines a new
initializer that dates an
intent.
In it, I extract the soup,
quantity, and options, and then
I initialize the order with
those values.
Great, this will be very
helpful.
Next, we need to make sure that
we donate the intent every time
the user places an order.
So, I'll go to the soup order
data manager, and, in the
placeOrder method, I'll add our
donation logic.
I create an INInteraction that
contains the intent of the
order, and then I just donate
that interaction, and that's it.
Finally, we need to handle the
intent.
I'll start by adding support in
the app itself, so I'll go to
the AppDelegate, and, in the
continueUserActivity, I'll add
support for it.
I check if the activityType of
the userActivity is equal to the
class name of the intent that I
want to handle.
If that's the case, I extract
the intent from the
userActivity, and I generate an
order with it.
Finally, I present the order
view.
So, since we're launching the
app, I'm assuming that the user
doesn't want to immediately
place the order but wants to
make some customizations before
placing it, so that's why I'm
presenting the order view
instead.
And, finally, let's add support
with an intents extension so the
user can run this intent in the
background.
I'll need to add an intents
extension first, so I'll go to
File, View, Target and select
the Intents Extension target.
I'll give it a name,
SoupChefIntents, and I click
Finish.
Since I've added a new target
where I'll use the intents, I
need to make sure that the
intent definition file is
included in that target.
So, I go back to the intent
definition file and add it to
that target.
Again, I don't want to generate
code in that target, so, in the
dropdown, I'll select No
generated classes.
I also want the extension to
have access to the same data as
the app, so I'll add it to the
same app group.
In the Project Settings, I
select the intents target and in
the capability step, I'll add it
to the same app group.
Great. Now, we're ready to
implement the intent handler
that was created with this
target.
First, I'll import our shared
framework, SoupKit [laughs].
Since we're going to handle the
OrderSoupIntent, this intent
handler needs to conform to the
OrderSoupIntentHandling
protocol.
This was generated as part of
our intent.
This protocol has one required
method, the handle method.
Let's implement it.
In the handle method, I get an
intent.
I create an order from that
intent, and, if that succeeds, I
place the order, and I call the
completion with an intent
response with a success code.
If I'm unable to create an order
from the intent, I call
completion with an intent
response with a failure code.
And that's it.
I've just added support for a
new intent in my app.
Let's try it out.
First, I'll need to donate the
intent.
So, I'll place another order.
Click the plus button and this
time I'm going to order a clam
chowder with croutons, and I'll
place the order.
Now, if we go back to the home
screen and pull down, I see my
donated intent.
Great.
[ Applause ]
I can tap it, and I'm presented
with a shortcut view and the
order button.
If I tap the order button, the
order will be placed in the
background, and it's ordered.
I can go back to the app and see
if it was actually ordered, and,
yeah, there is a new order in my
app.
Great, so easy.
[ Applause ]
I can also, instead of tapping
the order button, tap the
shortcut view, itself, which
will launch the app with the
shortcut, and, as I implemented
it, it shows the order view,
where I can customize the order.
So, I'll add cheese, too.
Who knows?
And I'll place the order.
Great. Finally, let's add the
shortcut to Siri.
I'll go to Settings, and I
scroll up to the Siri and
search.
Here I can select the shortcut
that I want to add to Siri.
In this case, I'll add the order
one clam chowder with croutons.
When I tap the record button, I
can say the phrase I want to
associate with the shortcut.
Soup time.
Now, they got it.
[ Applause ]
Let's take a step back and look
at what we just did.
We started by making an
NSUserActivity that was already
implemented in our app eligible
for prediction.
This allowed it to be suggested
and is a really easy way to
expose the content of your app.
Next, we defined a custom
intent.
This is really the best way to
represent a piece of key
functionality of your app.
In our case, that was ordering a
soup.
After defining the intent, we
made sure that we donate the
intent every time the user
placed an order inside of the
app.
And, finally, we handled the
intent, both in an extension to
support background execution and
in the app itself so the user
can launch the app with the
shortcut.
So, now that we've seen how you
can adopt shortcuts, let's take
a look at how those shortcuts
are suggested and what you can
do to make sure your users see
the best possible suggestions.
Every time a user performs an
action in your app and your app
donates this, the system will
look at the time, location, and
other signals.
For a time, we consider, among
other things, the time of day
and the day of the week.
Well, for the location, we look
at the overall location of the
user and see if it's a
significant location for that
user.
Let's see how the system now
uses these to make a suggestion.
Here, we'll just consider the
time.
Monday, at lunch, I order a
tomato soup with croutons.
That evening, I don't feel like
croutons, so I order a tomato
with red pepper instead.
Next day at lunch, I, again,
order a tomato soup with
croutons.
I keep doing this throughout the
week, and, on Friday, at lunch,
Siri might try to find a
suggestion for me.
It will look at my past behavior
and try to find a pattern in it.
And since it's lunchtime, and I
usually order a tomato soup with
croutons at lunchtime, Siri
might notice this and suggest
this to me, which is great.
It's exactly what I wanted.
So, this is all pretty high
level, so let's take a look at
how it actually works, starting
with NSUserActivity.
Imagine a user activity for the
place order screen in Soup Chef.
The user info dictionary could
contain three keys, soup,
quantity, and scroll position.
The last one is there, so, in
Handoff, you can bring the user
back to the exact position they
were last in.
Let's take a look at how this
can be suggested to the user.
We start by donating a user
activity where the soup is
tomato, the quantity is 1, and
the scroll position is 79
points.
Next, we donate a similar user
activity, but now scroll
position is changed to 110
points.
We keep doing this, and, at some
point, Siri will try to find a
suggestion again.
It will look at past behavior
and try to find a pattern of
equal user activities.
But since the scroll position is
so inconsistent over time, it
might not be able to find a
suggestion.
So, how can we fix this?
We can use the
requiredUserInfoKeys.
RequiredUserInfoKeys is an
existing property of a user
activity.
It represents the minimal amount
of information that is necessary
to restore the app to the state
that the user activity
represents.
And for suggestions it will be
used to determine which keys of
the user info dictionary will be
used to compare when looking for
patterns.
Let's apply this to a previous
example.
Now we specify that
requiredUserInfoKeys are soup
and quantity.
Again, we donate the user
activity where the soup is
tomato, the quantity is 1, and
the scroll position is 79
points.
But now the scroll position will
be ignored.
Next, we donate something
similar, and, again, the scroll
position is ignored.
We keep doing this, and, at some
point, Siri will try suggestion
again.
Now, I will look back and try to
find a pattern of equal user
activities.
And since it's no longer
considering the scroll position,
it might be able to say, "An
NSUserActivity with soup tomato
and quantity 1 is a good
suggestion for this user."
So, as you just saw, it's really
important to specify the right
set of keys as being required.
Otherwise, your users might not
get any suggestions at all.
So, that's how it worked for
user activity.
Intents work similarly but offer
you a lot more flexibility.
The main signal for intents are
the shortcut types that you
define.
Each shortcut type defines a
combination of parameters that
is valid for suggestion.
It's similar to the
requiredUserInfoKeys, but
instead of having just one set,
you can define multiple.
Let's apply this to our Soup
Chef app.
Earlier, I defined an
OrderSoupIntent with three
parameters, soup, quantity, and
options.
At the time, I only defined a
single shortcut type that
combined all of these
parameters, but, ideally, you
would define more shortcut
types, since that gives more
options to the system to find
patterns in your user's
behavior.
So, now I'll define three.
One shortcut type that combines
soup and quantity, one that
combines soup and options, and
one that combines all three
parameters.
Let's apply this to another
example.
Again, I start on Monday, at
lunch, by ordering a tomato soup
with croutons.
The Soup Chef app donates this
to the system, and the system
will split us up into all the
possible combinations based on
the shortcut types that I just
defined.
That evening, I order a tomato
soup with red pepper.
Again, it gets donated, and it
will be split up in all the
possible combinations.
Next day, at lunch, I order a
tomato soup with croutons.
It gets donated and split up.
I keep doing this throughout the
week, and, on Friday, at lunch,
Siri might try to find a
suggestion.
It might see that I often order
a single tomato soup.
But since it's lunchtime, it
also can see that, at lunchtime,
usually order a tomato soup with
croutons.
Since that is a more specific
shortcut, it will end up
preferring to suggest that.
So, I might get a suggestion to
order a tomato soup with
croutons.
Great. So, that's how
suggestions are made.
Let's now take a look at how to
make sure those suggestions are
good, and it all starts from
making good donations.
A good donation should be
something that is likely to be
repeated.
For user activity, there could
be some content they might look
at often.
Or, for an intent, there could
be an action the user would take
regularly.
You should make sure that the
payload of what you're donating
is consistent across all your
donations, since that is what
will be compared when looking
for patterns.
A good donation should also not
include a timestamp, since that
might not longer be relevant by
the time this donation would be
suggested.
For instance, a shortcut that
shows appointments for a
specific day is probably not
that useful, since, if you see
that the next day or later,
you're probably no longer
interested in the meetings of
that specific day.
A shortcut with a relative time,
however, is a lot more useful.
You should also make sure that
you donate exactly once for each
user action, even if that user
action involves multiple actions
inside your app.
Finally, selecting the correct
parameters of your intent is
also important.
So, let's take a look at two
possible types, starting with
enums.
You can define enums in your
intent definition file next to
your intents, and use it as the
types of your parameters.
We recommend that you use enums
whenever the values for a
parameter are bounded.
For instance, if you would add a
size parameter to a order soup
intent, it might make sense to
make that an enum, since the
possible sizes are probably just
small, medium, and large.
Using an enum will lead to
better suggestions and clearer
titles and subtitles for your
users.
To learn more about how enums
are used to generate titles and
subtitles, I recommend that you
watch the localization session.
Another type you can use is the
custom type.
Using a custom type will result
in an INObject and your
generated intent code.
An INObject combines an
identifier with a display
string.
The identifier can be used to
refer to an object internal to
your app, while the display
string contains the user
readable representation of that
object.
That way both your users and
your app always understands what
the value of this parameter is.
Finally, using an INObject also
prevents the possible dependency
between parameters.
Let me illustrate that.
There are two ways to represent
the combination of an identifier
with a display string.
You could add two parameters to
your intent, one for the
identifier, one for the display
string, or you could add a
single parameter using the
INObject.
With the first approach, you
have a dependency.
Since the display string depends
on the object as referenced by
the identifier, we discourage
having these dependencies as
they could cause issues when we
suggest this intent later.
A good shortcut should also have
an understandable title,
subtitle, and image.
It should represent what will
happen when the user taps the
shortcut, since it will be the
only thing the user will see
before interacting with it.
And, of course, you want to test
your shortcuts to make sure that
they look right and that they
behave as expected.
There are a couple of ways to do
that.
As I showed you earlier, we
added two new developer settings
that allow you to see your
recent donations on search and
on the lock screen, instead of
your regular Siri suggestions.
By enabling these, you can see
what your users will see when
those donations would be
suggested, and you can try
interacting with them to make
sure that they behave as
expected.
Another way to test your
shortcuts is by adding them to
Siri.
An easy way to test them then is
by editing the Xcode scheme to
automatically invoke Siri
without constantly having to say
the phrase.
In the scheme editor of an
intents extension there is the
Siri Intent Query field that you
can use to provide the utterance
to invoke Siri with.
And, finally, you can create a
custom shortcut in the Shortcuts
app that uses your shortcut.
This allows you to test the
behavior of your shortcut when
it's chained together with other
shortcuts or steps from the
Shortcuts app.
So, now that we've seen what a
good shortcut donation is and
how does donation get suggested
to your users, let's take a look
at a couple of privacy
considerations and how you can
make sure your user are never
upset by what is suggested to
them.
Your users expect that when they
delete something from within
your app that it's deleted for
good.
It's important to honor this so
you maintain your users' trust
and your so users aren't
presented with suggestions for
things that are not relevant to
them anymore.
So, if you donate shortcuts that
contain information that the
user can delete, you should make
sure to delete those donations
at the appropriate time.
Let's take a look at how to
delete donations, starting with
NSUserActivity.
There are two ways to delete a
donated user activity.
If you use Spotlight indexing
and you set the
relatedUniqueIdentifier, then
deleting the content from
Spotlight will automatically
delete the donated user
activity.
Just set the
relatedUniqueIdentifier on the
contentAttributeSet to the
identifier of the searchable
item that it matches with.
Then, when that searchable item
would be deleted, it would
automatically delete the user
activity.
If you don't use Spotlight
indexing, you can use the
persistent identifier property
on NSUserActivity.
This is a new property that you
can set so you can keep track of
your user activities and delete
them at the appropriate time.
To use it, just set the
persistentIdentifier property
before donating user activity.
Then, when you want to delete
it, you call
deleteSavedUserActivities with
the identifiers that you want to
delete.
You can also delete all your
donated user activities.
For instance, when your user
logs out, you can do that by
calling
deleteAllSavedUserActivities.
Intents have an existing API,
which is similar to this new
user activity API.
Since you donate intents through
INInteraction the leading and
donated intent also happens
through INInteraction.
An INInteraction has an
identifier and a group
identifier property that you can
set and then later use to delete
one or more donated
interactions.
Just set the identifier and or
group identifier before donating
the interaction.
Then, when you want to delete
it, you call delete with an
array of the identifiers that
you want to delete.
You can also delete all donated
intents with a shared group
identifier by calling delete
with the group identifier.
And, finally, just like
NSUserActivity, there is a way
to delete all your donated
intents by calling deleteAll on
INInteraction.
Please make sure to delete your
donations at the appropriate
time.
This will give your users the
best possible suggestions and
never make them wonder why
they're seeing suggestions for
things that are no longer
relevant to them.
So, now that we've looked at
different things to consider
when creating and donating
shortcuts, let's end by briefly
looking at what you can use to
create the best possible media
shortcuts.
We created a new intent that
works great with Shortcuts.
This intent is called
INPlayMediaIntent and allows you
to create and donate shortcuts
to play audio or video content.
When handling this intent in
your extension, you can choose
to have it handled by your app
in the background [inaudible].
This allows you to start audio
playback straight from your app.
Besides being suggested in
search and on the lock screen,
shortcuts with this intent will
also be suggested in the
playback controls on the lock
screen when the user connects
their headphones, making it even
easier for them to start
listening to your content.
And, finally, shortcuts with
this intent work great on the
HomePod.
Just add a play media shortcut
to Siri on your iPhone and
invoke it on your HomePod.
The audio will start playing
from your phone through HomePod.
We also created a new API that
allows you tell the system about
new content they might be
interested in.
This is great for periodical
content, where the content that
you would want to be suggested
to your users isn't something
they've listened to or watched
before.
So, those are a couple of things
that we have added to make great
media shortcuts.
Now, let's summarize what we
just talked about.
Shortcuts enable powerful, new
experiences with your apps.
It provides new ways to engage
your users by exposing your app
throughout the system in a
variety of places.
So, just search the lock screen,
the Siri Watch Face on your
Apple Watch, and in Siri itself.
You can also use it in the new
shortcuts app.
You can adopt shortcuts by using
NSUserActivity, which is a
really easy way to expose the
content of your app.
Or you can use intents which
provides you with a deeper
integration in the system and
can unlock entirely new
experiences for your users.
[ Applause ]
For more information, our
session is 211, and you can find
our page on developer.apple.com.
You can also find us in the labs
throughout the week.
Thank you so much for coming.
And we can't wait to see what
shortcuts you'll create.
Enjoy the rest of your
conference.
[ Applause ]