以前、ReactiveCocoaを利用したiOSサンプルアプリケーションを公開しましたが、それと同様のWatchサンプルアプリをGitHubで公開しました。
アプリ自体は非常に単純です。 iPhoneアプリではHddServiceCodeが表示される以外の実装はしていません。
契約ごとのクーポン残量の合計と、当日のクーポン利用状況のみが表示されます。
項目をタップすると、その契約にひも付いている電話番号と当日のクーポン利用状況が表示されます。
グランスでもほとんど同じ情報を表示します (ただし一つめの契約のみ)。
なお、Apple Watch側でブラウザを起動できませんので、あらかじめ本体アプリ側でOAuth認証を行っておく必要があります。
また、コンパイルして利用するにはだいたい次のようなことが必要です。
- IIJMioクーポンAPIを取得してコードに埋め込む
- entitlementを自分向けに書き替える
- 署名を自分向けに書き替える
Watchアプリの構成
一般的なWatchアプリの構成は次の通りで、本アプリも同じです。
- 本体アプリ
- Watch Extension
- WatchKitアプリ (ストーリーボードのみ)
普通のiOSアプリにターゲットにWatchKit Appを追加すると下の2つが追加されます。
Watch Extensionには (設定次第ですが) 次のような3つのコントローラクラスが追加されます。
- InterfaceController (Watchアプリ)
- NotificationController (Watch通知)
- GlanceController (Watchグランス)
これらを別々に実装していくことになります。 今回は上2つを実装して、グランスは放置しています。
Tips
Groupを縦に並べたいときはLayoutをVerticalにする
WatchKit向けのUIではいろいろ配置に制限があったりします。
Groupには方向が決まっていて、デフォルトが横になっているので注意。
TableRowにNSObject派生クラスを指定
TableRow
はUITableViewCell
みたいなものなのですが、該当するものはWatchKitにはありません。
かわりに、NSObject派生クラスをつくって、それをクラス指定してやれば利用できるようになります。
class TableRow : NSObject { @IBOutlet weak var hddServiceCode: WKInterfaceLabel! @IBOutlet weak var couponTotal: WKInterfaceLabel! @IBOutlet weak var couponUsedToday: WKInterfaceLabel! }
セグエで呼ばれるメソッドがテーブルとそれ以外で異なる
- テーブルには
contextForSegueWithIdentifier:inTable:rowIndex:
- テーブル以外は
contextForSegueWithIdentifier
Watch実機実行時にストーリーボードが変わってないことがある
ストーリーボードの内容を更新しても、Watch側で更新されていないことがあるみたいです。
新しく追加したUI部品でnilエラーになっていたりするのはこれが原因です。
iPhone側のWatchアプリで開発アプリをuninstall → Installすればよいです。
実機実行前にエラー “A signed resource has been added, modified, or deleted.” が出て実行できない
OS X 10.10.3, Xcode 6.3.2, CocoaPods 0.37.1の環境では、再度実行しようとすると次のようなエラーが出てしまいます。
そのため、毎回実行する前に、DerivedData
を削除する必要がありました (毎回フルコンパイルすることになるのでキつい)。
Appアイコン
ターゲットWatchAppを追加するだけでは、WatchKit App向けのアイコンを追加することはできません。
アセット上でNew App Iconをして作り直すのがてっとり早いみたいです。
また、このアセットをのTarget MembershipにWatchKit Appを追加する必要があるかもしれません。
KeyChain Sharing
Apple Watchでは単体でブラウザを起動できないので、Watch単体でOAuth認証はできません。
そこで、本体とWatchKit ExtensionでKeyChain Sharingを有効にした上で、
- 本体アプリ側でOAuth認証で得られたアクセストークンを取得してKeyChainに入れる
- WatchKit Extensionでそれを利用して、IIJMioのクーポンAPIにアクセス。情報を表示する
というようにする必要があります。
なお、セキュリティ面を考慮してアクセストークンにはキーチェインを利用していますが、そういう必要がない場合には後述するNSUserDefaultsを利用してもよいでしょう。
本体がロックされているときにキーチェインにアクセスできない
Watchアプリでは、iPhone本体がロックされているときには次のようなエラーが表示されます。
これは、本体がロックされているときには、Extensionがキーチェインにアクセスできないことが原因です (SecItemCopyMatchingなどでerrSecInteractionNotAllowed
が返されます)。
この詳細については次の記事を参照してください (この記事バックグラウンドフェッチについて書かれていますが、エクステンションでも同じことが言えます)。
WatchKit Extensionがアクセストークンを取得したら、その後はずっと利用できますが、何らかのタイミングでWatchKit Extensionが終了することがあります。 そうするとトークンが失なわれて、再起動時に本体をロックされているときにはアクセストークンが得られずに、(今回のアプリだと) APIにアクセスできなくなります。
NSUserDefaultsで前の状態を記録
KeyChainにアクセスできないときには、何も情報が表示できなくなるので、以前の情報を保存しておいてエラー時にそれを表示するようにしました。
情報の保存にはNSUserDefaultsを利用しました。これについては以前記事を書いたので、それを参照してください。
Safx: App GroupsとNSUserDefaultsでiOSアプリ間のデータを共有する
このアプリでは本体側から得た情報も、WatchKit Extensionで利用する予定だったので、App Groupsをオンにしていますが、現状では本体側は実装されていませんので得に意味がありません。
関連リンク
- safx/MioDashboard-swift · GitHub
- Safx: App GroupsとNSUserDefaultsでiOSアプリ間のデータを共有する
- Gilt: iOS7でbackground fetchを利用するとログアウトしてしまうバグへの対応 - ワザノバ | wazanova
- Safx: IIJmioクーポンAPIを使ったiOSのTodayウィジェットをつくってみた
- Safx: IIJmioのどら焼きをいただきました
- Safx: IIJmioクーポンスイッチAPIのiOSサンプルアプリで使ったライブラリの雑感を書いてみる
- Safx: IIJmioのクーポンスイッチAPIを利用したiOSサンプルアプリケーションを公開しました
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。