iOS10の新機能SiriKitでできる16のこと

**この記事は現段階（2016/7/18）で一般に公開されている情報を元に作成しています**

# SiriKit
![スクリーンショット 2016-06-20 13.47.43.png](https://qiita-image-store.s3.amazonaws.com/0/45525/a5102fde-3ff2-c74d-90a8-660b1ac551de.png)

iOS10からサードパーティのアプリでもSiriを使うことができるようになりました。

ただし開放されたと言ってもなんでもできるようになったわけではなく、**できるようになったことは意外と少なく、大きく分けると6種類、細かく分けると16個**です。

## Intents Domain

以下が今回[アプリがSiriに提供できるカテゴリの一覧](https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/SiriDomains.html#//apple_ref/doc/uid/TP40016875-CH9-SW2)です。先ほど6種類と書いたものがこちらです。

* VoIP Calling
* Messaging
* Photo Search
* Payments
* Workouts
* Ride booking


これらは**Intents Domain**と呼ばれ、Siriを使って提供できるサービスのカテゴリを表しています。アプリごとに1つだけではなく複数提供することができるようになっています。どれを提供するかはInfo.plistに記載します。

**今回発表されたSiriKitではここに挙げられているDomain以外のことはできません。**

なのでSiriをアプリに組み込もう！と思っても上記に該当するサービスを適切な形でアプリが提供できなければSiriとの連携はできないと考えて良いでしょう（工夫次第だと思います）。

## User intention 

User intentionは直訳すると"ユーザーの意図"ですが、Intents DomainごとにUser intentionが定義されています。以下がその一覧です。[こちらが資料](https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/SiriDomains.html#//apple_ref/doc/uid/TP40016875-CH9-SW2)。

| Intents Domain | User intention | 概要 |
|-----------------|------------------|------------------|
| **VoIP Calling**  |  Start an audio call | 音声通話の開始 |
| | Start a video call | ビデオ通話の開始 |
| | Search the user’s call history | 通話履歴の検索 |
| **Messaging**  |  Send a message | メッセージの送信 |
| | Search for messages | メッセージの検索 |
| **Photo Search** | Search for photos | 写真の検索 |
| | Play a photo slideshow | スライドショーの再生 |
| **Payments**  |  Send a payment to another user | 他のユーザーへの支払い |
| | Request a payment from another user | 他のユーザーへの支払い要求 |
| **Workouts** | Start a workout | ワークアウトの開始 |
| | Pause a workout | ワークアウトの一時停止 |
| | Resume a workout | ワークアウト再開 |
| | End a workout | ワークアウト終了 |
| | Cancel a workout | キャンセル |
| **Ride booking** | Book a ride | 乗車予約 |
| | Get the status of a booked ride | 乗車の予約状況 |

おそらく将来的にはできることが増えるのでしょうが、**現在はこの16個のみ**となっています。

LINEなどのメッセージアプリはVoIPによる音声/ビデオ通話の開始、メッセージの送信などが対応可能になるのではないでしょうか。ワークアウト系のアプリは基本的にSiriで操作ができるようになりそうですね。

ただし上記に当てはまらない機能、例えばカメラアプリをSiriで起動してセルフィーを撮ってもらう、とかは今のところできません。


## 実装方法

上に挙げた**User intentionごとに`Handler`, `Intent`, `Response`クラスが定義**されています。


### 1. ターゲットの追加
まずはターゲットの追加ですが、ExtensionテンプレートにIntents Extensionというものが追加されているので、これを追加すればOKです。

### 2. Info.plistの編集

次にInfo.plistの編集を行います。

<img width="417" alt="スクリーンショット 2016-06-23 13.52.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/45525/a59cc0fb-94c3-5d29-4d17-3f1b11c40376.png">

追加したターゲットのInfo.plistにNSExtension　> NSExtensionAttributes > IntentsSupportedにサポートするIntentのクラス名を記載します。

例えばワークアウトの開始をSiriでサポートする場合は`INStartWorkoutIntent`を追加します。

IntentsRestrictedWhileLockedはデバイスがロックされている最中に操作を行えないようにする場合に指定します。

### 3. Extensionの実装

Siriからの入力を受けとってSiriに結果を返す際の流れは以下のようになっています。

![resolve_confirm_handle_cycle_2x.png](https://qiita-image-store.s3.amazonaws.com/0/45525/ebbaee02-e8a8-3428-0f94-85b30862285f.png)
画像は[こちら](https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/CreatingtheIntentsExtension.html#//apple_ref/doc/uid/TP40016875-CH4-SW1)より引用

上記の図の流れとしては、

1. `Resolve`でパラメータの解決
2. `Confirm`で最終確認
3. `Handle`でタスクの実行

という流れになります。

`Confirm`と`Handle`で`Response`を返していますが、Siriはこれを使って結果の表示を行います。`Response`には`NSUserActivity`オブジェクトが含まれており、これを使ってアプリへ状態を引き継ぐことができます。

## 実装方法

実装については[UnicornChat](* https://developer.apple.com/library/prerelease/content/samplecode/UnicornChat/Introduction/Intro.html#//apple_ref/doc/uid/TP40017332
)というApple公式のサンプルコードがあるので、それを参考にすると良いです（ベータのため環境によっては動作しないことがあります）。


以下がSiriからのリクエストを処理する際の主要なクラス及びプロトコルについては[こちら](https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/SiriDomains.html#//apple_ref/doc/uid/TP40016875-CH9-SW2)にまとまっています。

全ては説明しきれないので、ワークアウトを開始するためのIntentを例に挙げてみます。

### SiriKitによるワークアウト開始に必要なオブジェクト

SiriKitを使ってワークアウトを開始する際に必要になるオブジェクトです。

| Start a workout  | Objects |
|-----------------|------------------|
| Intent | `INStartWorkoutIntent` |
| Response | `INStartWorkoutIntentResponse` |
| Handler  | `INStartWorkoutIntentHandling` protocol |

#### `INStartWorkoutIntent`
Intentの[`INStartWorkoutIntent`](https://developer.apple.com/reference/intents/instartworkoutintent)はSiriがユーザーの言葉を解釈して変換してくれるオブジェクトです。プロパティに`workoutName`などが用意されており、ワークアウトを開始するために必要な情報がここに入ってきます。

#### `INStartWorkoutIntentResponse`
[`INStartWorkoutIntentResponse`](https://developer.apple.com/reference/intents/instartworkoutintentresponse)は`INStartWorkoutIntentHandling`内で処理結果をSiriに伝えるために使用するオブジェクトです。

#### `INStartWorkoutIntentHandling`
[INStartWorkoutIntentHandling](https://developer.apple.com/reference/intents/instartworkoutintenthandling)で`INStartWorkoutIntent`, `INStartWorkoutIntentResponse`を使ったパラメータの解決や処理の実行を行います。


## まとめ

ざっくりとまとめると以下のようになります。

* 6種類のIntents Domainをサポート
  * 全部で16のことができる
  * 逆にそれ以外のことはできない
* 実装したいドメインのプロトコルの実装を行う
* Resolveでパラメータのバリデーション, Confirmで確認, Handleでタスクの実行
  * ユーザーの入力をSiriが解釈してIntentオブジェクトに変換してくれる

なお、アプリでSiriを使った機能を有効にするには、カメラへのアクセス等と同様にユーザーの許可が必要になります。許可の取得には[`INPreferences`](https://developer.apple.com/reference/intents/inpreferences)の[`requestSiriAuthorization(_:)`](https://developer.apple.com/reference/intents/inpreferences/1829429-requestsiriauthorization)を使用します。

対応するドメインが少ないですが、今回のSiriKitはiOS10の目玉機能とも言えるので是非ともアプリに組み込みたいですね!!

SiriKitを触ってみた感想としては、**周りに人がいると独り言を言っているみたいでSiriKitの動作確認はとてもやりづらい**です。なるべく密室で一人で行うことをオススメします😎


## 資料

### スライド
iOS/Android開発Tips共有会である[potatotips #30](http://potatotips.connpass.com/event/32665/)で[SiriKitについて発表した際のスライド](https://speakerdeck.com/mnat44/sirikit)です。

UTの書き方、Embedded frameworkを使用した実装のTipsについても記載しています。

### ドキュメント
* https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/index.html
* https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/SiriDomains.html#//apple_ref/doc/uid/TP40016875-CH9-SW2
* https://developer.apple.com/library/prerelease/content/documentation/Intents/Conceptual/SiriIntegrationGuide/SpecifyingCustomVocabulary.html#//apple_ref/doc/uid/TP40016875-CH6-SW1


### APIリファレンス
* https://developer.apple.com/reference/intents
* https://developer.apple.com/reference/intentsui


### WWDC Sessions
* https://developer.apple.com/videos/play/wwdc2016/217/
* https://developer.apple.com/videos/play/wwdc2016/225/

### サンプルコード
* https://developer.apple.com/library/prerelease/content/samplecode/UnicornChat/Introduction/Intro.html#//apple_ref/doc/uid/TP40017332