HandoffをつかってApple Watchの作業をiPhoneに引き継ぐ

# Handoffとは

Handoffは、iOS 8およびOS X 10.10から追加された機能です。

[Handoff Programming Guide](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) には次のように書かれています。

> Handoff is a capability introduced in iOS 8 and OS X v10.10 that transfers user activities among multiple devices associated with the same user.

Handoff機能により、同じユーザに結びつけられた複数のデバイス間で、作業（Activity）を引き継ぐことができます。

![continuation_2x.png](https://qiita-image-store.s3.amazonaws.com/0/8292/26f330d9-bbc7-b3a9-1b77-847f3a657037.png)


# Apple Watchへの応用

Apple WatchでもこのHandoff機能を使うことが可能です。例えばApple Watchで読んでいたブログ記事を、iPhone側に引き継いでそのまま読み続けることができます。

# 実装方法

例えば、記事番号3（内部的なIDの持ち方を `article_id = 3` とします）の記事をApple Watchで読んでいたとします。腕を上げたまま記事を読み続けるのが疲れてきたので、iPhone側に引き継いで読むケースを想定してみます。

## WatchKit側の実装

ユーザがいつでも作業を引き継げるように、記事が表示されたタイミングで「ユーザが記事番号３を読んでいるよ」というアクティビティを他のデバイスに通知しておきましょう。コードは次のようになります。

```objc
NSDictionary *userInfo = @{@"article_id" : @"3",
    @"category" : @"sports"};
[self updateUserActivity:@"com.example.watch" userInfo:userInfo webpageURL:nil];
```

この例では、他のデバイスに `article_id=3, category=sports` という情報を通知しています。（categoryは何となく付けただけなので気にしないでください）

![スクリーンショット 2015-02-27 19.58.18.png](https://qiita-image-store.s3.amazonaws.com/0/8292/4dcbf5db-5f00-1223-484c-3157942af744.png)

`updateUserActivity:` の第一引数にはアクティビティを受信側で判別するための文字列（activityType）を指定します。アクティビティの種類によって受信側の処理を切り替えたい時に使用するためのものだと思われます。 

ちなみに、`userInfo` に nil を指定することは出来ないことに注意して下さい。万が一、nilをセットしてしまうとアプリがクラッシュする可能性があります。

## iPhone側の実装

<b>注意：現在、シミュレータによるHandoff機能のテストはできないようです。Apple Watchはこの記事を書いている時点（2/27）では発売されていないため、実機でのテストはできません。よって、ここから先の情報は「実機ではこう動くはず」という予想の内容になります。実機が入手でき次第、この内容も更新する予定です。</b>

Info.plistの `NSUserActivityTypes` に先ほど指定した `activityType` を設定します。

![3AA60C71-9D26-46A1-9E69-C06D3151D0D3.png](https://qiita-image-store.s3.amazonaws.com/0/8292/e005e34a-adc3-2c0e-b076-5f40a266cb81.png)

これでApple WatchからのHandoffを受け取ることが可能になりますが、WatchKit側で `updateUserActivity:` を実行しただけではiPhoneアプリは起動しません。ユーザが意識的にiPhoneを手に取り、ロック画面を開く必要があります。

iPhone側が他のデバイスからのアクティビティを受信すると、下図のようにロック画面左下に送信元アプリのアイコンが表示されます。このアイコンを指で上方向に持ち上げることで、userInfo情報を渡した状態で該当アプリが起動します。

![スクリーンショット 2015-02-27 20.09.30.png](https://qiita-image-store.s3.amazonaws.com/0/8292/474ca848-e074-2274-c36c-42da44fa5cfc.png)


このとき呼ばれるのが、AppDelegate内の次のメソッドになります。

```objc
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void(^)(NSArray *restorableObjects))restorationHandler
{
    // 記事番号を取り出す
    NSString *articleId = userActivity.userInfo[@"article_id"];
    
    // 記事を画面に表示する処理を書いていく
    …
}
```

このメソッド内で記事を表示する処理を書いていきます。

第三引数の `restorationHandler` も結構重要なのですが、説明すると長くなるので、興味のある方はググってみるとよいでしょう。

# 最後に

今回は、<span style="color: #dd830c">HandoffでApple Watchの作業をiPhoneに引き継ぐ方法</span>を解説しました。

この他にもHandoffを使って、GlanceやPush NotificationからWatch Appにアクティビティを通知することも可能です。Glanceで表示している内容をWatch App側に伝えたい場合などに便利です。

![スクリーンショット 2015-02-27 21.19.07.png](https://qiita-image-store.s3.amazonaws.com/0/8292/9411bba8-4045-419d-2e0a-c2eb01acb784.png)

Glance→Watch Appへのアクティビティ通知は、[@haranicle](https://twitter.com/haranicle) さんによる下記の記事で詳しく解説されています。（いつも参考にさせて頂いてます）

[WatchKitでHandoff](http://blog.haranicle.net/watchkit_handoff/)



# 参考リンク


* [WatchKit Framework Reference](https://developer.apple.com/library/prerelease/ios/documentation/WatchKit/Reference/WatchKit_framework/index.html#//apple_ref/doc/uid/TP40014968)
* [Handoff Programming Guide](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html)
* [WatchKitでHandoff](http://blog.haranicle.net/watchkit_handoff/)