Swift Regex Deep Dive
iOS MacOur introductory guide to Swift Regex. Learn regular expressions in Swift including RegexBuilder examples and strongly-typed captures.
Siri is Apple’s intelligent personal assistant. Siri allows you to use your voice to interact with your iOS, watchOS, tvOS and macOS devices. As with many Apple technologies, Apple has made it easier for developers to integrate their apps with Siri through SiriKit. This series explores SiriKit and how you can use it to expose your app’s functionality through Siri. In Part 1 we looked at the basics of SiriKit, and in Part 2 we explored Resolve, Confirm and Handle. Now we’ll take a look at those final details that will help you ship your Siri-enabled iOS app.
As it stands, BNRun contains most of what’s needed to work with Siri. But to allow Siri to work best with BNRun, there are a few final touches that should be implemented.
A user can ask Siri “What can you do?” to discover what they can do with Siri, including what third-party apps can do with Siri. When asked this, Siri will show the app, and selecting the app will show a list of sample phrases. These sample phrases come from the AppIntentVocabulary.plist
that is added to the application’s Base.lproj
(not the extension’s bundle).
Specifically, the IntentPhrases
key must have IntentExamples
entries for every IntentsSupported
key in the Intents extension’s Info.plist
. Additionally, if you have a base AppIntentVocabulary.plist
, every localization of your app/extension must have a localized AppIntentVocabulary.plist
. When apps are submitted to the App Store, the AppIntentVocabulary.plist
(both Base and localized versions) are sent to Siri for processing; those files remain on the server and will be specific to that version of the app. These phrases help the user understand how Siri and your app interact, but they also help Siri itself understand how your app can be invoked.
The other part of the AppIntentVocabulary.plist
is the ParameterVocabularies
. This is an optional array of dictionaries to help Siri understand app-specific terms: terms specific to your app, used by any user of your app. This is useful if an app uses vocabulary in a nonconventional way or a way completely unique to the app. Note these terms are global. If you have user-specific terms – terms unique to this particular app user, like their custom photo tags – you’ll want to look at INVocabulary
.
If you tried running any of the samples, you may have noticed Siri has a hard time with the app name of “BNRun”. To improve Siri’s recognition of the app name, be sure to provide a CFBundleDisplayName
in your application’s Info.plist
. Yes, this value is also displayed under the app’s icon in the iOS home screen, so it’s important to understand how this value interacts with Siri, even if your app doesn’t use Siri. If your app is localized, be sure to include an InfoPlist.strings
file for the app’s localization that includes a localized CFBundleDisplayName
.
Changing “BNRun” to have a CFBundleDisplayName
of “Big Nerd Run” makes it much more natural to interact with Siri. But the reuse of the CFBundleDisplayName
may not be workable for your app. New in iOS 11 is support for alternative app names. In the application’s Info.plist
, the INAlternativeAppNames
is an array of dictionaries that describe other names the app can go by, within the context of Siri. Each dictionary contains INAlternativeAppName
, which is a string containing the alternative app name; and optionally INAlternativeAppNamePronunciationHint
, which is a “sounds like” pronunciation hint for the alternative name.
Siri can be accessed in various ways, including from the lock screen. Depending what your app does, give consideration to the ability to access your supported Intents from the lock screen. Some intents, like INSendPaymentIntent
cannot be directly accessed from the lock screen. If your Intent is one that can be accessible from the lock screen but you don’t want it to be accessible (e.g. you have a “secure” messaging app, so sending messages can only happen from an unlocked device):
Info.plist
.NSExtensionAttributes
of your NSExtension
entry, add IntentsRestrictedWhileLocked
(an array of string values).IntentsSupported
entries that you wish to restrict from the lock screen, add the Intent’s name as an entry for IntentsRestrictedWhileLocked
.When an intent is listed under IntentsRestrictedWhileLocked
, if the user invokes the Intent from the lock screen, the OS will prompt the user to unlock the device before the Intent can proceed to be handled.
IntentsRestrictedWhileLocked
is good for restricting access from the lock screen, but what if you need a little more authorization for your operation? Use Touch ID or Face ID. There’s nothing special here – it’s just standard LAContext
handling. And of course, using a passcode is an acceptable fallback if the device does not support biometrics.
If your app needs to support payments, Apple recommends using Apple Pay (perhaps even the SiriKit Payments Domain) as it is a secure API for processing payments.
One final step before you ship your Siri-enabled app? Test it. All of those IntentPhrases
? Make sure they actually work. Custom vocabulary? App name synonyms? If they’re worth adding to your app, it’s worth verifying they work correctly. It’s also worthwhile to take the time to run through all possible permutations of your supported Intents and their parameters; there’s many ways a user could invoke Siri, so make sure you resolve, confirm and handle the user’s intent with aplomb. Because different users could invoke Siri differently, it’s also worthwhile to beta-test your app to gain as much coverage for the multitude of invocation angles. And yes, explore XCUISiriService
for unit testing your Siri interface.
func testStart500MileWalkWithSiri() {
XCUIDevice.shared.siriService.activate(voiceRecognitionText: "walk 500 miles in Big Nerd Run")
}
If BNRun was a real app, I would take the time to support the full range of the Workout Domain. I hope with what I’ve provided you can see it wouldn’t be too much effort to complete the suport. You can find the latest revision to the sample code, including the vocabularies, app names and a simple unit test in the sample code repository. Use that code as a starting point, finish out the Workout Domain support, such as pausing and resuming the workout. It will be a good way to begin exploring SiriKit.
I recommend watching the WWDC 2016 Session 217 “Introducing SiriKit” video. All WWDC videos regarding Siri and SiriKit are worth watching, but this one especially since it covers best practices and provides handy tips for ensuring a great Siri user experience for your app.
Voice interfaces are only going to grow in power, functionality, and popularity. It’s worthwhile to explore what SiriKit can do today and see how you can make your app Siri-enabled. Even if you cannot take advantage of Siri today, you can think about Apple’s view of the future for iOS and watchOS app development via embedded frameworks and app extensions and begin work to ensure your app can take advantage of the coming technologies.
And if you’re having trouble implementing SiriKit or other features into your iOS or watchOS app, Big Nerd Ranch is happy to help. Get in touch to see how our team can build a Siri-enabled app for you, or implement new features into an existing app.
Our introductory guide to Swift Regex. Learn regular expressions in Swift including RegexBuilder examples and strongly-typed captures.
The Combine framework in Swift is a powerful declarative API for the asynchronous processing of values over time. It takes full advantage of Swift...
SwiftUI has changed a great many things about how developers create applications for iOS, and not just in the way we lay out our...