【iOS】SiriショートカットをAppに導入する

SiriショートカットはiOS 12で追加されたAppを素早く起動するための機能です。AppにSiriショートカットを導入することで、ロック画面からAppを起動したり、ショートカットAppを経由してAppを起動することができるようになります。また、Appの設定や状態をパラメータとしてショートカットに設定することができ、ユーザの目的に沿った状態でAppを起動することができます。
本記事ではNSUserActivity とIntent を使用してSiriショートカットを実装する方法について説明します。
Siriショートカットの実装方法
Siriショートカットを実装する方法は以下の2パターンがあります。
-
NSUserActivityを利用する方法 -
Intentを利用する方法
NSUserActivity を利用する方法は実装が簡単ですが、ショートカットに設定したパラメータをショートカットAppで変更することができません。一方、Intent を利用する方法は実装が若干煩雑ですが、ショートカットに設定するパラメータをショートカットAppで変更することができ、よりインタラクティブなショートカットを作成することができます。Appの仕様に合った実装方法を選択しましょう。
NSUserActivityを利用した実装
ショートカットタイプを定義する
以下のようにInfo.plistファイルにショートカットタイプを定義します。

ショートカットタイプを登録する
ここで重要なのがisEligibleForSearch とisEligibleForPrediction です。isEligibleForSearch をtrue にすることで、アクティビティに設定したタイトル名でSpotlight内での検索が可能になり、isEligibleForPrediction をtrue にすることで、ショートカットが使用可能になります。
userInfo はアクティビティの状態を復元したい時に使用します。後ほど説明するショートカット起動をハンドリングする際に、userInfo に格納した辞書データを取り出すことでアクティビティ保存時の状態を復元することができます。
作成したNSUserActivity オブジェクトをUIResponder のuserActivity にセットすることで、アクティビティのショートカットが有効になります。
上記のコードを追加した後にAppを起動して、ショートカットを有効状態にしましょう。
ショートカットが有効状態になると、ロック画面のSpotlightでショートカットが表示されるようになります。

また、ショートカットAppでショートカットを登録することができるようになります。

ショートカット起動のハンドリング
ショートカットでAppを起動すると、UIApplicationDelegate のapplication(_:continue:restorationHandler:) またはUISceneDelegate のscene(_:continue:) が呼び出されます。これらのメソッドで渡されるNSUserActivity オブジェクトのactivityType で処理を分岐させることができます。
・SceneDelegate.swift
・AppDelegate.swift
以上がNSUserActivity を利用したSiriショートカットの実装方法になります。実装自体はそこまで難しくなく、ロック画面やSiriショートカットからAppを起動することができれば良い時は、NSUserActivity を利用した実装が適していると言えます。
Intentを利用した実装
年齢、飲酒経験、飲酒頻度をパラメータとするショートカットの実装を例に説明します。
Intent定義ファイルの追加
Intent を作成するため、プロジェクトにIntent定義ファイルをプロジェクトに追加します。「File」>「New」>「File」の順に選択すると以下のようなファイル一覧ダイアログが表示されます。

この中からSiriKit Intent Definition Fileを選択します。ファイル名は任意の名前を指定し、「Create」を選択するとIntent定義ファイルがプロジェクトに追加されます。
Intentの新規作成
Intentエディタの左下に表示されている「プラス」ボタン >「New Intent」の順に選択するとIntent定義ファイルに新しいIntent が追加されます。

今後、Intent を追加する場合を考慮して、Intent の名称を任意の名前に変更しておきましょう。今回はIntent 名をMedicalCheckup としました。

Intentの定義
Intent のメタデータを定義します。ユーザが目にする部分なのでメタデータの定義は慎重に行います。

- 「Category」項目で選択した内容はSiriのメッセージを変化させます。
Intentの目的と一致するものを選択します。 - 「Title」フィールドに入力した内容はショートカットのタイトルになります。ショートカットAppでショートカット作成した時に、ショートカットのタイトル箇所に表示されます。
- 「Description」フィールドに入力した内容はショートカットの詳細説明になります。ショートカットAppでショートカット作成した時に、ショートカットの説明箇所に表示されます。
- 「Confirmation」チェックを有効にすると、Siriと対話しながら
Intentを実行する時に実行確認が行われます。Siriと対話しながらIntentを実行するためにはResolve処理を実装する必要がありますが、本記事では実装しないので無効にします。 - 「Widgets」チェックを有効にすると、
IntentConfigurationを使用したWidgetでIntentを使用することができるようになります。本記事ではWidgetを実装しないので無効にします。 - 「Configurable in Shortcuts」チェックを有効にすると、ショートカットAppでショートカットを作成することができるようになります。
- 「Suggestions」チェックを有効にすると、
Intent実行に関するSiriからの提案が有効になります。
Intentパラメータの定義
Intent に設定するパラメータの定義を行います。こちらもユーザが目にする部分なのでパラメータの定義は慎重に行います。今回作成するIntent に定義するパラメータは以下の三つです。
- 年齢 (
Integer型) - 飲酒経験 (
Bool型) - 飲酒頻度 (
Enum型)
年齢、飲酒経験パラメータを下記の手順に従って定義します。
- 「Parameter」項目左下に表示されている「プラス」ボタンを選択して新しいパラメータを追加します。
- 「Display Name」フィールドはパラメータ名になります。ショートカットAppでショートカットにパラメータを設定する時に表示されます。
- 「Type」はパラメータの型になります。コード側で扱うのに適した型を選択します。
- 「Array」チェックを有効にすると、パラメータを配列として扱うことができます。今回は無効にします。
- 「Configurable」チェックを有効にすると、ショートカットAppでパラメータを設定することができるようになります。
- 「Resolvable」チェックを有効にすると、Siriと対話しながら
Intentを実行する時に、Siriがパラメータを質問するようになります。本記事ではResolve処理を実装しないので無効にします。 - 「Parent Parameter」はパラメータ間の関係性を定義します。後程説明しますので、「None」を選択して下さい。
- 「Input」項目はパラメータの初期値と、ショートカットAppでパラメータを設定する時のUIを定義します。
- 「Prompt」フィールドはSiriと対話しながら
Intentを実行する時、Siriがユーザにパラメータの値を質問する時のフレーズを定義します。
Enumの定義
飲酒頻度に関するパラメータは他のパラメータと違い、飲酒頻度を表す型は用意されていないので自身で定義する必要があります。今回は飲酒頻度を要素とするEnum を定義します。
Intent定義ファイルを選択して表示されるIntentエディタの左下に表示されている「プラス」ボタン > 「New Enum」の順に選択するとIntent定義ファイルに新しいEnum が追加されます。

今後、Enum を追加する場合を考慮して、Enum の名称を任意の名前に変更しておきましょう。今回はFrequency としました。


- 「Enum - Display Name」フィールドに入力した内容はパラメータ名になります。ショートカットAppでパラメータを設定する時に表示されます。
- 「Cases」項目はEnumの要素を定義することができます。「Cases」項目左下に表示されている「プラス」ボタンを選択することで要素を追加することができます。
- 「Index」フィールドは要素のインデック番号を定義します。
- 「Cases - Display Name」フィールドに入力した内容は要素名になります。ショートカットAppでパラメータを設定する時に、パラメータのメニュー項目として表示されます。
Frequency 型の定義が完了したら、パラメータの「Type」フィールドに定義したFrequency 型が表示されるようになりますので飲酒頻度を表すパラメータを定義します。
パラメータ間の関係性の定義
あるパラメータの値によっては他のパラメータを表示しないといった、パラメータ間の関係性を定義することができます。例えば、今回追加した飲酒頻度パラメータは飲酒経験パラメータと関係性を持たせることができます。飲酒経験がある時は飲酒頻度パラメータの入力を要求し、飲酒経験がない時は飲酒頻度パラメータの入力は不要とさせることができます。

- 飲酒頻度パラメータの「Parent Parameter」フィールドに飲酒経験パラメータを指定します。
- 「Show If Parent」メニュー項目は「has exact value」を指定します。
- 「Value」メニュー項目は「true」を指定します。
このように設定することで、飲酒頻度パラメータは飲酒経験パラメータがtrue の時だけ、入力が要求されるようになります。
ショートカットに表示するメッセージの定義
ショートカットApp内でショートカット入力時に表示するメッセージを定義します。

- 「Summery」フィールドに入力した内容は、ショートカットのパラメータ設定時に表示されます。
Siriからの提案時に表示するメッセージの定義
Siriからの提案時に表示するメッセージを定義します。

- 「Summery」フィールドに入力した内容は、Siriからの提案時に表示されます。
CustomIntentの生成
CustomIntent(MedicalCheckup )の定義が完了した後にプロジェクトのビルドを行うと、定義したCustomIntent(MedicalCheckup )クラスのコードが自動生成され、コード内で使用することができるようになります。

ショートカット起動のハンドリング
ショートカットでAppを起動すると、UIApplicationDelegate のapplication(_:continue:restorationHandler:) またはUISceneDelegate のscene(_:continue:) が呼び出されます。NSUserActivity の時と同様に、これらのメソッドで渡されるNSUserActivity オブジェクトのactivityType で処理を分岐させることができます。Intent で作成したショートカットで起動した時は、activityType にIntent 名が入っています。
・SceneDelegate.swift
・AppDelegate.swift
ショートカットの動作確認
ショートカットAppを起動し、ショートカットを作成をします。

ショートカットの追加を行うことができるようになっています。またパラメータの設定やパラメータ間の関係性も動作しています。

IntentのDonate(提供)
Intent をSiriにDonateすることで、SiriがIntent を実行したいタイミングを予測し、ショートカットを提案してくれるようになります。以下のコードでは年齢パラメータは20、飲酒経験パラメータはTrue 、飲酒頻度パラメータは.onceAWeek のIntent をDonateしています。
Donateの動作確認
iOSの設定Appから「デベロッパ」を選択し、「Display Recent Shortcuts」をオンにしておきます。

Appを一度起動した後にiPhoneのロック画面の状態でしばらく時間を置いた後、iPhoneのロック画面を表示すると、Siriがショートカットの実行を提案してくれます。

iOS 16でロック画面ウィジェットを開発できるようになったことで、NSUserActivity を利用したSiriショートカットのメリットは以前に比べて小さくなっていると感じました。Intent で作成したSiriショートカットだと、ショートカットAppでショートカットのパラメータを柔軟に変更できるので、設定項目が多いツール系Appでは力を発揮できるのではないでしょうか。
参考資料
Adding User Interactivity with Siri Shortcuts and the Shortcuts App
Introduction to Siri Shortcuts
Introducing Parameters for Shortcuts
Discussion