Apple Watch アプリ開発について(Watch OS 1のとき)

※以下はWatch OS 1の情報です。Watch OS 2も今後対応して行こうと思います。

Apple Watch アプリ(以下、Watch App)の開発を担当させてもらって、Apple Watch も購入しました。なので、開発について思ったことを書こうと思います。
まだ書きかけですが特に[ハマったところ]や[Tips]あたりがApple Watch アプリ開発の参考になれば嬉しいです。
参考：https://developer.apple.com/watchkit/

##概要
・Apple Watch アプリ(以下、Watch App)は単体では提供できず、iPhoneアプリにBundleする形でApp Storeから提供する。
・Watch Appは、常にiPhone側とWifiかBluetoothで通信して動作しているため（設計思想で後述）、iPhoneが近くにないと動作できない。
・Watch Appに対応するにはXcode6.2以降でProjectの下側の + を押して、[Apple Watch]-[Watch App]を選択して[Next]ボタンを選択します。
![projectAppWatch.png](https://qiita-image-store.s3.amazonaws.com/0/37373/c36eb608-fb0e-51de-6a4d-1f2dcedddb26.png "projectAppWatch.png")

そうすると、WatchKit AppとWatchKit Extensionが作成されます。
![appleWatch3.png](https://qiita-image-store.s3.amazonaws.com/0/37373/293c3d87-fce0-ec68-fd83-3602f3935264.png "appleWatch3.png")


##できること
Watch App本体、Glance、DynamicNotificationの３つをApple Watch内に組み込めます。

###Watch App本体
・アプリ本体。以下のWatchアプリ一覧の中からユーザーが選択して起動する。
・Watch App開発時は必須。
　![IMG_3095.PNG](https://qiita-image-store.s3.amazonaws.com/0/37373/b51a0b2b-6ff2-83ec-ef6e-c7f06f47a04b.png "IMG_3095.PNG")

###Glance
・iPhoneでいうところのウィジェット。時計画面から下スワイプで表示される一枚の画面。
・スクロールできるような画面やボタンやスライダーなどのUIは置けない。
・タップするとWatch App本体が起動する。
・Watch App開発時は必須ではない。
　以下はApple標準の天気アプリのGlance。
　![IMG_3096.PNG](https://qiita-image-store.s3.amazonaws.com/0/37373/52a4acc9-86bb-4932-088c-cb66e0efb559.png "IMG_3096.PNG")

###Dynamic Notification
・Push通知やLocal通知受信時に表示される画面(画像はdeveloper appleのページから)。
　Glanceと違って、スクロールできるような画面やボタンなどのUIも配置でき、iOS8での追加機能であるNotificationAction（通知にボタンを表示できる機能）のボタンも表示される。
　![longlook_calendar_2x.png](https://qiita-image-store.s3.amazonaws.com/0/37373/e9b0e588-5b47-8d6d-4306-67bbaa743952.png "longlook_calendar_2x.png")

・Watch App開発時に必須ではなく、Dynamic Notificationを実装しなかった場合はStatic Notificationという決まったフォーマットの表示がされる。画像などを使ったオリジナルな表示を行いたい場合にDynamic Notificationを実装する。
・Dynamic Notificationを実装していても、以下のような状態だった場合はStatic Notificationが表示される。
　　- 電池が残り少ない
　　- Dynamic Notification内の処理に時間がかかり過ぎている
　　- Dynamic Notification内の処理に不具合(BAD ACCESSESSなど)が発生している
・Static NotificationはApple Watchに対応していないアプリでも表示される。
・iPhoneがスリープ状態のときにしか表示されない。

##設計思想
Watch App開発時に用意するものは、WatchKit App(StoryboardとResource)とWatchKit Extension(プログラム)があります。

###WatchKit App
・Apple Watch側にインストールされる方。
・こちら側にはStoryboardとResource(Images.xcassetsと多分info.plist)しかインストールされない（つまりプログラムはApple Watch側にインストールされない）。

###WatchKit Extension
・iPhone側にインストールされる方。
・WatchKit Appでの処理を実装する(アプリ起動時や表示時、ボタンタップ時の処理など)。

上記を踏まえてWatch Appの処理をざっくりフローにすると、以下のような感じだと思います。
![AppWatchAppFlowchart.png](https://qiita-image-store.s3.amazonaws.com/0/37373/b98cffec-0745-1fca-9ced-79f78cbcbfcf.png "AppWatchAppFlowchart.png")
Glanceだとボタンタップなどは検知できません（タップされるとWatch App本体が起動する）。
DynamicNotificationはローカル通知受信処理メソッド（didReceiveLocalNotification:withCompletion:）やプッシュ通知受信処理メソッド（didReceiveRemoteNotification:withCompletion:）を別途用意する必要があります。

##ハマったところ

####WatchKit App側の画像はImages.xcassetsへの追加が必須。
・png画像をそのまま WatchKit AppのTarget MembershipsにチェックしておけばiOS Simulator上だと表示できるのに、Apple Watch実機だと表示されない。
　Watch App対応をリリースしたのはApple Watch発売前だったため、iOS Simulatorでテストしてたので気がつきませんでした。

####application:handleWatchKitExtensionRequest:reply:内で時間のかかる処理（通信など）を行うときはbeginBackgroundTaskWithName:expirationHandler:(バックグラウンドタスク起動)しないとならない。
・これは普通にReferenceに書いてましたけど、iOS Simulatorだとバックグラウンドタスク時間が無限になっていたので気がつきませんでした。

####iOS SimulaterだとLocal通知はデバッグできない。
・Push通知は、プロジェクトにWatchKit App追加時に自動生成されるPushNotificationPayload.apnsファイルでデバッグできる。

##Tips
####application:handleWatchKitExtensionRequest:reply:のデバッグ

　1. 対象のiPhoneアプリを起動。
　2. XcodeでWatchKit Appをデバッグ実行。
　3. [Debug]-[Attach To Process]-[対象のiPhoneアプリ]を選択。するとiPhoneアプリ側のプロセスにアタッチしてapplication:handleWatchKitExtensionRequest:reply:に設定したBreakpointにも止まるようになる。
　　![AppleWatchDebug.png](https://qiita-image-store.s3.amazonaws.com/0/37373/ebf08501-9f7a-b8fb-589e-c81454a739fe.png "AppleWatchDebug.png")


</br>
</br>
####Watch App対応アプリはAppleで優先的にReviewしてくれるかも(2015/4/29時点)
・わたしのときは、AppleWatch対応リリース時(Review待ち5日くらい)も、その後のUpdate(Review待ち2日くらい)も早かったです。

</br>
</br>
####iPhoneアプリ起動中の場合、Watch AppからiPhoneアプリをプログラムにて操作できる。
・WatchKit Extentionから[WKInterfaceController openParentApplication:reply]経由でできます。
・でも、逆（iPhoneアプリからWatch Appを操作）はできないと思います。