読者です 読者をやめる 読者になる 読者になる

Apple TVアプリの開発(focus-based interfaces)

今日から、Apple TVアプリの開発について本格的に書いていこうと思います。

今後の流れ

今回は、iOSとtvOSの大きな違いである、focus-based interfacesについて取り上げ、 次回以降については、

  • Siri RemoteのTouchPad以外の部分のイベントハンドリングについて
  • tvOSでも使えるライブラリについて
  • ユーザーのエンゲージメントを高めるTop Shelfについて

といった順で書いていきます。

focus-based interfacesとは

ざっくり言うと、UIKitのクラスを

  • Focusを取ることができる要素(UIButtonやUITextFieldなど)
  • Focusを取ることができない要素(UILabelなど)

に分け、Siri Remoteから指示をFocusを受け取ることができる要素の移動に反映させてしまおう、という考え方です。

tvOSでこの考え方が採用された背景としては、Apple TVが他のデバイスと違い次のような特徴を持っていることが挙げられます。

  • iPhoneiPadのように、画面上のオブジェクトに直接触れることができない
  • リモコンとディスプレイの距離が比較的遠い

iOSとtvOSにおけるUIKitの違い

tvOSは上記したように、focus-based interfacesを採用しているため、 UIView及び、その継承クラスに対して、以下のようなメソッド、プロパティが追加されています。

  • func canBecomeFocused() -> Bool
  • var focused: Bool { get }

Focus EngineはcanBecomeFocused()の戻り値によって、Focusを当てる当てないの判断を下します。

また、UIViewControllerやUIWindowなど、UIFocusEnvironment Protocolを採用しているクラスは、 preferredFocusedViewによって、最初にFocusを当てるべきViewを特定することになります。

Focus移動の例

ここからは、サンプルプロジェクトを通じて Focusがどのように移動するか見ていきます。

Focusable Object間の移動(FocusableViewController)

preferredFocusedViewにボタンBが設定されているため、 画面遷移時には、ボタンBにフォーカスが当たっています。
ボタンAとボタンB、ボタンAとボタンCは相互に移動できますが、ボタンBからボタンCには直接移動することができません。
f:id:nerd0geek1:20160123170628p:plain

Focusable/Non-Focusable Object間の移動(NotFocusableViewController)

ボタンDには、userInteractionEnabled = falseが設定されています。
そのため、ボタンAから右にスワイプすると、ボタンBにフォーカスが移動します。
また、UILabelはフォーカスを受け取らないため、ボタンAから下にスワイプすると、
ボタンCにフォーカスが当たります。 f:id:nerd0geek1:20160123170635p:plain f:id:nerd0geek1:20160123170639p:plain

FocusGuideを用いた移動(FocusGuideViewController)

この例では、UIFocusGuideを追加しています。 そのため、ボタンBから下にスワイプすると、ボタンCにフォーカスが移動し、 ボタンCから右にスワイプすると、ボタンBにフォーカスが移動するようになっています。 f:id:nerd0geek1:20160123171350p:plain f:id:nerd0geek1:20160123171628p:plain

まとめ

かなりざっくりですが、tvOSで採用されたfocus-based interfacesが どのように動くかを見ていきました。
次回は、Siri-Remoteに関して説明していきます。

参考

サンプルコード