Siri Shortcuts on Apple Watch
Learn how to take advantage of Siri and Shortcuts on the Apple Watch without any intervention required from the iOS companion app. By Mark Struzinski.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Siri Shortcuts on Apple Watch
30 mins
- Getting Started
- Running the App
- Setting up Portal Requirements
- Creating an App Group
- Configuring Your Account
- Understanding Siri Shortcuts and Intents
- Using NSUserActivity-Based Shortcuts
- Using Intents-Based Shortcuts
- Executing the App Remotely
- Adding an Intent-Based Shortcut
- Adding the Intent Definition File
- Configuring Types
- Configuring a New Intent
- Setting up Intent Parameters
- Explaining Parameters
- Understanding More Parameters
- Configuring the Shortcuts App
- Defining Suggestions
- Defining Siri’s Response
- Adding the Intents Extensions
- Adding Framework Dependencies
- Configuring for Builds
- Configuring Identifiers
- Enabling Entitlements Files
- Updating Info.plist Files
- Generating Intent Code
- Sharing Intent Handling
- Resolving Parameters
- Connecting the Handlers
- Testing Your Intent
- Testing With Voice
- Validating Input
- Adding Your App to the Watch Face
- Where to Go From Here?
Resolving Parameters
Inside resolveOunces(for:with:)
, add the following code:
// 1
guard
let ounces = intent.ounces?.intValue,
ounces != 0
else {
let result = TrackIntakeOuncesResolutionResult.needsValue()
completion(result)
return
}
// 2
let result = TrackIntakeOuncesResolutionResult.success(with: ounces)
completion(result)
Here’s what you’re doing:
- Check for the ounces variable, cast to
Int
and make sure it isn’t zero. If any of these checks fail, return aneedsValue()
result, which will invoke the disambiguation response you set up in your intent handler. - If all conditions are satisfied, return a success result.
Next, inside resolveHydrationType(for:with:)
, add the following code:
// 1
let hydrationValue = intent.hydrationType.rawValue
guard
let hydrationType = HydrationType(rawValue: hydrationValue),
hydrationType != .unknown
else {
let result = HydrationTypeResolutionResult.needsValue()
completion(result)
return
}
// 2
let result = HydrationTypeResolutionResult.success(with: hydrationType)
completion(result)
Here’s what you’re doing:
- Get
rawValue
from the enum passed in the arguments. Attempt to createHydrationType
fromInt
and ensure it doesn’t come back.unknown
. If any of these checks fail, return aneedsValue()
result, which will start the disambiguation flow. - If all conditions are satisfied, return a success result.
Once you satisfy all those conditions, handle(intent:completion:)
gets called.
Fill that method out now with the following code:
// 1
let hydrationValue = intent.hydrationType.rawValue
// 2
let drink = DrinkType(rawValue: hydrationValue)
// 3
guard
let drinkType = drink,
let ounces = intent.ounces?.intValue
else {
let response = TrackIntakeIntentResponse(
code: .failure,
userActivity: nil)
completion(response)
return
}
// 4
let item = LogEntry(drinkType: drinkType, ounces: ounces)
let dataManager = DataManager()
dataManager.save(entry: item)
// 5
let response = TrackIntakeIntentResponse(
code: .success,
userActivity: nil)
completion(response)
Here’s what you’re doing above:
- Get the hydration value from the shortcut’s input.
- Create a
DrinkType
from the value. - Check to ensure you have valid
DrinkType
andounces
input, otherwise call completion with a failure result. - Create
LogEntry
and saving it to the data store. - Call completion with a successful response.
Note that the completion handler argument is using the generated types from your intent definition file.
Connecting the Handlers
Now, you have to invoke the shared handler from your intents extensions. In each extension, Xcode generated a file for you named IntentHandler.swift. Open each one and update the body of handler(for:)
to the following:
return TrackIntakeIntentHandler()
The code above creates a new intent handler for any shortcut invoked from your app on iOS or watchOS.
Testing Your Intent
That was a lot of setup, but now you can test your intent in a shortcut!
Follow these steps to see your new intent in action:
- Select the Hydrator scheme. Build and run to your physical device.
- Open the Watch app on your phone and install the Hydrator app on the watch.
- Open the Shortcuts app on the phone.
- Tap + at the top of the screen to create a new shortcut.
- Next, tap Add Action.
- Then, tap Apps.
- Scroll down to find Hydrator and select it.
- Tap Track Intake.
- Tap Show More to expand options. You should see Ounces and Hydration Type appear.
- For each option, tap into the value and select Ask Each Time from the keyboard accessory view.
- Tap the ellipsis (⋯) button on the top right to open the shortcut’s settings.
- Name the shortcut Hydrate Me and ensure Show on Apple Watch is enabled.
- Tap Done to return to the shortcut, then tap Done again to save your shortcut.
- On your watch, open the Shortcuts app. You should see the Hydrate Me shortcut you just created near the top.
- Tap to run it and answer the prompts.
Testing With Voice
Next, try running your shortcut solely by voice.
- Push the digital crown to go back to the watch face.
- Hold in the crown or say “Hey, Siri” to invoke Siri.
- Say “Hydrate me”.
- Now, you should get voice prompts for both input items.
Validating Input
Now, open the Hydrator app on the watch. Tap refresh on the bottom right. You should see all the items you added via shortcuts now show up in the app!
Adding Your App to the Watch Face
Finally, watchOS 7 adds the ability to put shortcuts directly on the watch face as a complication. Adding the Shortcuts complication to your watch face gives you the ability to select a specific shortcut to run when you tap that complication. Now your users have one-tap access to your shortcut!
Where to Go From Here?
You can download the completed project files by clicking the Download Materials button at the top or bottom of the tutorial.
Shortcuts are an exciting and dynamic addition to Apple’s platforms. In this tutorial, you learned how to build shortcuts to run locally on the watch. You also learned to avoid remote execution by ensuring you build your intent extension for watchOS.
You can also investigate many related areas, including customization options for your flows, donating to the system, confirmation flows and more complicated disambiguation flows. Apple has released extensive documentation for SiriKit. We also have an excellent tutorial on SiriKit to help you take your shortcuts to the next level.
Take all these tools and see what kind of incredible experiences you can build for your users.
We hope you enjoyed this tutorial, and if you have any questions or comments, please join the forum discussion below!