[ Music ]
[ Applause ]
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.
[ Applause ]
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.
[ 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.
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.
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.
[ 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.
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.
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 ]