I'm trying to create an App Shortcut so that users can interact with one of my app's features using Siri. I would like to be able to turn this shortcut on or off at runtime using a feature toggle.
Ideally, I would be able to do something like this.
struct MyShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
// This shortcut is always available
AppShortcut(
intent: AlwaysAvailableIntent(),
phrases: ["Show my always available intent with \(.applicationName)"],
shortTitle: "Always Available Intent",
systemImageName: "infinity"
)
// This shortcut is only available when "myCoolFeature" is available
if FeatureProvider.shared.isAvailable("myCoolFeature") {
AppShortcut(
intent: MyCoolFeatureIntent(),
phrases: ["Show my cool feature in \(.applicationName)"],
shortTitle: "My Cool Feature Intent",
systemImageName: "questionmark"
)
}
}
}
However, this does not work because the existing buildOptional
implementation is limited to components of type (any _AppShortcutsContentMarker & _LimitedAvailabilityAppShortcutsContentMarker)?
.
All other attempts at making appShortcuts
dynamic have resulted in shortcuts not working at all. I've tried:
- Creating a
makeAppShortcuts
method that returns[AppShortcut]
and invoking this method from within theappShortcuts
- Extending AppShortcutsBuilder to support a
buildOptional
block isn't restricted to a component type of(any _AppShortcutsContentMarker & _LimitedAvailabilityAppShortcutsContentMarker)?
- Extending AppShortcutsBuilder to support
buildArray
and using compactMap(_:) to return an empty array when the feature is disabled
I haven't used SiriKit before but it appears that shortcut suggestions were set at runtime by invoking setShortcutSuggestions(_:), meaning that what I'm trying to do would be possible. I'm not against using SiriKit if I have to but my understanding is that the App Intents framework is meant to be a replacement for SiriKit, and the prompt within Xcode to replace older custom intents with App Intents indicates that that is indeed the case.
Is there something obvious that I'm just missing or is this simply not possible with the App Intent framework? Is the App Intent framework not meant to replace SiriKit and should I just use that instead?
Sadly I don't believe this is possible, as AppShortcutsProvider requires a static array. It also does some ML magic under the hood at compile time that likely precludes an array of dynamic AppShortcuts from being supported.
To handle this, if you need to put the AppShortcut in there before the feature is available / enabled, I would do the feature flag check inside of the AppIntent's perform method instead. If the feature is disabled you can return a dialog to indicate that to the user, or run the intended behavior normally if the feature is enabled.
Otherwise, I'd leave the AppShortcut out until you are ready for that feature to be live in prod and exist in future versions of your app.
AppShortcuts is certainly the easiest and most straightforward way to integrate AppIntents & Siri into your app simultaneously, but for now SiriKit still seems to be supported as well. AppIntents are definitely the future, as they are the API of choice to work with Apple Intelligence. I'd definitely recommend using AppIntents if this is a new feature in your app.