Shortcutsに対応させた話こんにちは。モバイルエンジニアの高野です。Shortcutsではないでしょうか。blogですので今回はどのようにこの機能を開発していったかを紹介します。どんな機能?弊社のプロダクトには、クレジットカードや銀行口座の明細をAPIなどから取得する同期機能が備わっており、定期的にバックグラウンドで明細取得されます。任意のタイミングで明細を取得して、最新の状態で会計処理をしたい時もしばしばあります。Shortcutsに対応させて、好きなタイミングでSiriを使って簡単に明細取得をできるようにしました。Siriに「口座を同期して」と話しかけると、登録してあるクレジットカード・銀行口座の同期を開始し、新しい明細の取得が完了したらPush通知で知らせてくれる、という体験になります。Shortcutに対応させたことで、Siriに話しかける方法だけではなく、Spotlightのサジェスト・場合によってはロックスクリーンにもShortcutが表示される(ロックスクリーンに表示される条件はブラックボックスですが)ことになります。WWDCのセッションの中で、Shortcutとして提供する機能はアプリ内で繰り返し行われる重要な機能が適していると言及されていましたが、今回それにピッタリの題材になったかなと思います。Shortcutsに対応させるために行うことここから、今回の機能のために必要だった作業の流れを紹介していきます。Shortcutsに対応させるための開発には、SiriKitを利用します。frameworkが含まれています。対応するにあたって参照したドキュメントは以下です。Chefも参照しました。DocumentationIntentの定義さて、ではまずはIntentを定義します。IntentというのはSiriが受け付けられるリクエストのことを指します。今回は「口座を一括同期する」と言うIntentが必要なわけですが、システムが標準で提供する特定ドメイン(MessagingやPayment等)のIntentとは合致しないため、カスタムインテントを作っていきます。fileという新たに追加された形式のファイルを使って、Intentのタイトルやサブタイトル、パラメータ、リクエストに対してのレスポンスを定義していきます。File」から作成できます。今回の定義は非常にシンプルで、タイトルや説明文などを記述しているだけです。Shortcutに対応させることができますね。fileの内容に基づいたprotocolやclassを定義するコードが自動生成されます。Classes”と設定します。することで、共有Frameworkに向けてのみコード生成されるようになり、コンフリクトが避けられます。Extensionを用意します。Extensionを作る必要はありません。Extensionを用意する必要があります。Extensionを用いてバックグランドでタスクを完了できるようにした方がいいのではないかと思います。Extensionの役割の大部分は、Siriとアプリが提供するShortcutを機能させるロジックとの橋渡しになります。今回私が実装した内容も、部分的に省略していますがだいたい以下のようなレベルの簡素な物です。}}Siriからの要求をハンドリングするメソッドが、自動生成されたprotocolで定義されているので、そのメソッドの中で共有Frameworkに実装されたロジックを実行する感じです。required」という項目がありますが、Shortcutの実行前にユーザーに確認を促すべきアクションなどの場合はこれにチェックを入れ、IntentHandlerでconfirmするメソッドを実装する形になります。Extensionを用意していたとしても、バックグラウンドでの処理ができなかった場合などに対応するため、application(_:continue:restorationHandler:)は実装するように、とドキュメントに書かれています。Extensionの間で共有する機能をこの共有Frameworkに実装します。「Intentの定義」のところで少し触れた共有Frameworkのことですね。Membershipの設定を変更し、このFrameworkに含まれるようにします。弊社のアプリでは、Siriから実行するための口座同期を開始するAPIの定義などがこのFrameworkに含まれています。Extensionに対応していないアプリでも、サービスのコアとなる機能をこのレイヤーに切り出しておくと設計としても良いのではないかと思います。ShortcutのDonation最後の仕上げとして、Shortcutとして提供したい機能をSiriに提供します。Shortcutsに対応させる機能が利用される度にDonationするコードを実行します。ドキュメントによると、この時の時刻や位置等の環境を元にSiriがサジェストしてくれるようになるということです。Siri経由でその機能が実行された場合は、システムは暗黙的にそのことを認知するようで、明示的にDonationする必要なありません。ShortcutsとしてSiriに提供するようにと書かれています。アクションは、NSUserActivityかINInteractionを使ってSiriに提供できますが、今回はINInteractionを使って、以下のようなコードでDonationしました。}エラー処理など省略していますが、Donationするのに最低限必要なコードはこれだけです。これを、アプリ内で口座の同期ボタンがタップされる際に実行しておくようなイメージです。Shortcutsには対応できていて、SpotlightやロックスクリーンへのShortcut表示は行われる下地が整った状態になります。ここで更にSiriらしく、アプリ内で任意の音声フレーズを今回作成したShortcutに割り当て、音声でShortcutを実行できるようにする方法を紹介します。Siriボタンを画面に表示します。INUIAddVoiceShortcutButtonのイニシャライザは、enumとして定義されるINUIAddVoiceShortcutButtonStyleを引数として受け、それに応じてボタンの外観を変更します。whiteOutlineが定義されており、その中からアプリに合う物を選ぶことになります。.white)view.addSubView(button)表示はこのようになります。INUIAddVoiceShortcutButtonのdelegateを設定しておくと、このボタンがタップされた時にdelegateのpresent(_:for:)メソッドが呼ばれます。その引数に渡されるINUIAddVoiceShortcutViewControllerを表示することで、フレーズを登録する画面がをユーザーに提供することができます。フレーズが登録されている場合は自動的にボタンのラベルが変化し、ボタンをタップすると、編集画面を起動するためのpresent(_:for:)メソッドが呼ばれます。現時点でINUIAddVoiceShortcutButtonのリファレンスに載っているサンプルコードだと、ボタンにaddTargetで設定したセレクタでINUIAddVoiceShortcutViewControllerインスタンスを作って画面に表示している箇所があり、この理由は分かりませんが、delegateを使ったほうがシンプルに書けると思います。Shortcutsに対応した際の流れを紹介しました。dayという、いわゆる20%ルール的な制度を設け、その中でエンジニアが自律的に作りたいものを作っていけるようにしています。Shortcuts対応はその中から生まれた機能です。この制度を使ってこれまでに色々な機能のリリースや、開発基盤の整備などが行われています。