この記事はCyberAgent Developers Advent Calendar 2016の23日目の記事です。

こんにちは。AbemaTVでiOS、tvOSを開発している波戸(@dekatotoro)と申します。最近は黙々とtvOSアプリの開発をしていましたので、今回はiOSアプリ開発者向けにtvOSアプリ開発のポイントについて紹介したいと思います。


AbemaTV on Apple TV

AbemaTVはオリジナルの生放送コンテンツや、音楽、スポーツなど様々な番組を見ることができるインターネットテレビ局です。動画配信サービスなのでTVデバイスと非常に相性が良いものになります。tvOS向けのアプリは先月の11月25日から提供を開始していますので、Apple TVを持っている方は是非使ってみてください。

appletv_press

 

Apple TV 4th generation

まずApple TVについてです。Apple TVは、第1世代〜第4世代まであるのですが、開発者にtvOS SDKが提供され、Apple TV用アプリの開発・配信ができるようになったのは第4世代からとなります。まずは、Apple TV第4世代の概要について見ていきたいと思います。

第4世代Apple TVは2015年9月に発表されて、2015年10月30日に発売されたので、発売から1年ちょっと経過しています。

apple-tv

スペックは以下のようになっています。CPUはA8 Dual-Coreでメモリが2GBなのでiPhone 6のCPUとiPhone 6sのメモリと同等で、単純に比較はできませんが、iPhone 6とiPhone 6sの中間のスペックくらいでしょうか。

  • 64-bit A8 processor
  • 32GB or 64GB of storage
  • 2GB of RAM
  • 10/100Mbps Ethernet
  • WiFi 802.11a/b/g/n/ac
  • 1080p resolution
  • HDMI 1.4
  • New Siri Remote / Apple TV Remote

Apple TVに付属するリモコンですが、上部のマットな部分はTouch Surfaceと呼ばれている部分で、Swipe/Touch/Selectができます。物理ボタンとして、MenuHomeSiriPlay/PauseVolumeボタンがあります。

remote-and-interaction-remote-diagram_2x

tvos_swipetvos_clicktvos_tap

 

開発手法

開発手法は大きく分けて2つあります

  • Traditional Apps

  • Client-Server Apps

Traditional AppsはiOSと同様にUIKitで開発するもので、Client-Server AppsはTVMLやTVJSといったWeb technologyを使って開発する手法になります。今回はTraditional Appsについての内容です。

 

制限

大きな制限事項としてアプリケーションバンドルのサイズ制限とStorageの制限があります。

tvOSアプリのバイナリサイズは200MBまでとなります。アプリによって大きなリソースが必要な場合オンデマンドリソースを使う必要があります。

またStorageに関しても以下のような制限があります。

tvos_storage


TemporaryDirectoryCacheDirectoryはOSによって消される可能性があります(
アプリケーションの実行中は削除されません)。tvOSではLibraryDirectoryDocumentsDirectoryが使えないので、RealmやSqliteのようなdatabase fileもCacheDirectoryに保存することになります。purgeされる可能性を考えると、DBはdisk保存じゃなくてonMemoryを検討してもいいかもしれません。

 

レイアウト

tvOSアプリの画面レイアウトは1920 x 108016:9の画面解像度に設計します。画像もiOSみたく@1x, @2x @3xと複数用意する必要はなくtvOS用に@1xの一つだけになります。

tvos_layout1

 

全体的なデザインですが、古いTVだと端が見切れて隠れてしまうことがあるので、画面の端は余白を空けておくことが推奨されています。

tvos_layout2

 

古いTVなどで端が見切れて隠れてしまう現象は、オーバースキャンアンダースキャンがあり、テレビやプロジェクター側の設定で調整すると直る場合があります。ただ、ユーザーがなかなか設定できることに気づかないことが多いと思うので、見切れても問題ないように余白を設けたデザインにしたほうが良さそうです。

 

tvos_over_under_scan

 

フォーカスして拡大しても問題ないようにパディングを設けること、大きな要素でもコンテンツを1画面に伸ばさず複数あるというヒントを残すことが推奨されています。

tvos_layout3

tvos_layout4

 

レイアウトに関してはtvOS Human Interface Guidelinesに豊富な例を示してくれているので一読することをおすすめします。

 

ジェスチャーtvos_gesture

リモコンのTouch SurfaceSwipe/Touch/Selectの操作は、GestureRecognizerやEventで検知できます。

UITapGestureRecognizer

UITapGestureRecognizerはallowedPressTypesにUIPressTypeを指定できます。

  • upArrow

  • downArrow

  • leftArrow

  • rightArrow

  • select

  • menu

  • playPause

upArrow/downArrow/leftArrow/rightArrowはTouch Surfaceを左右上下の位置で軽く触る、selectはTouch Surfaceを押し込む、menu/playPauseは物理ボタンの押下で発生するイベントです。

 

UISwipeGestureRecognizer

UISwipeGestureRecognizerはUISwipeGestureRecognizerDirectionを指定できます。

  • right
  • left
  • up
  • down

Touch Surface左右上下のSwipeの入力イベントになります。

その他にもUIPanGestureRecognizerUIResponderのPress EventMotion Event等も使えます。Motion EventはViewフォーカス時のparallax効果を表現できます。使用例は以下のブログがわかりやすいと思います。

Replicating tvOS Parallax Focus Effect on Custom UIViews

 

フォーカス

tvOSではフォーカスという概念があり、基本的にView間の移動はフォーカスによって行います。ここがiOSと大きく違うところでもあります。

フォーカスはフォーカスエンジンがデフォルトでViewを決定します。 通常は、このViewは画面の左上に最も近いフォーカス可能なViewになります。

search_hierarchy_2x

デフォルトでフォーカスされるUIKitクラス

  • UIButton
  • UITextField
  • UITableView
  • UICollectionView
  • UITextView
  • UISegmentedControl
  • UISearchBar

UILabelなどデフォルトでフォーカスされないViewをフォーカスさせるには、UIViewのcanBecomeFocusedをoverrideする必要があります。また、UITableView、UICollectionViewに関してもフォーカスするCellをtableView:canFocusRowAtIndexPath:collectionView:canFocusItemAtIndexPath:で決定することができます。

基本的にはフォーカスエンジンに任せておけば良いのですが、フォーカスエンジンの検索エリアのサイズは、現在フォーカスされているViewのサイズで決定するため、意図したフォーカスにならない場合もあります。その場合は、自前で制御する必要があります。

 

フォーカスエンジンは、View階層のフォーカス動作を定義するUIFocusEnvironmentプロトコルに従ってフォーカスを制御しています。

tvos_focus

このプロトコルがフォーカス制御のキモになります。以下のUIKitクラスがこのプロトコルに準拠しています。

  • UIView
  • UIViewController
  • UIWindow
  • UIPresentationController

ViewやViewControllerでUIFocusEnvironmentプロトコルの以下の実装をoverrideすることでフォーカス動作を制御できます。

  • preferredFocusEnvironment
  • shouldUpdateFocus(in:)

フォーカスされた場合のVIewの拡大/縮小などデフォルトの動作を変更したい場合はdidUpdateFocus(in:with:)をoverrideすることで実現できます。UITableViewのCellはデフォルトのフォーカスアニメーションがありますが、UICollectionViewはありません。cellの中にadjustsImageWhenAncestorFocused がtrueのImageViewがあればImageが拡大しますが、cell自体のフォーカスアニメーションをつけたい場合はoverrideして実装する必要があります。

また、Swipe/Touch/Selectなどのジェスチャーや何らかの条件でフォーカスをupdateしたい場合はsetNeedsFocusUpdateでフォーカスエンジンに更新をリクエスト、即座に更新したい場合はupdateFocusIfNeededを呼び出します。ここら辺はAutoLayoutを彷彿とさせますね。

上でふれましたが、UIImageViewにはadjustsImageWhenAncestorFocusedというpropertyがあるのでこれをtrueにしておけばUIImageのフォーカスアニメーションとインタラクションがつきます。

tvos_focus

その他、UITableViewとUICollectionVIewについてはremembersLastFocusedIndexPathというpropertyがあり、trueにすると最後のフォーカスを覚えておいてくれます。

 

ライブラリ

最後にライブラリについてですが、多くのライブラリがtvOSにも対応しています。iOSに特化したUI系のライブラリはもちろんtvOSで使えませんが、逆にtvOSに特化したライブラリもいくつあります。

awesome-tvos

参考までにAbemaTVのtvOSアプリで使っているライブラリは以下になります。大きいところで言うとRxSwiftSQLite.swiftProtocolBuffersなどでしょうか。UI周りのライブラリはあまり使っておらず、基本的には標準のUI部品で実装しています。

  • RxSwift
  • RxCocoa
  • SQLite.swift
  • ProtocolBuffers-Swift
  • SwiftyUserDefaults
  • SDWebImage
  • Cartography
  • AttributedLabel
  • SwiftDate
  • Cheetah
  • SpringIndicator
  • CryptoSwift
  • KeychainAccess
  • ReachabilitySwift
  • Fabric
  • Crashlytics

 

まとめ

今回はtvOSアプリの開発についてポイントを絞っていくつか紹介しました。iOSと大きく違うポイントは今回紹介したUI/UX入力イベントの扱いフォーカスの制御ではないかと思います。

tvOSはリモコンを使って操作するので、iOSほど自由度もなく、他のアプリも標準のUIを採用しているところが多いので、基本的には標準のUI/UXに準拠した方が良いでしょう。

操作感は入力イベントの扱いフォーカスの制御がキモですが、フォーカスのデバッグ機能も用意されているので、iOSアプリを開発している方ならすぐに理解できるのではないでしょうか。

発売から1年以上経過したApple TV第4世代ですが、ストアを見ると外資系のアプリばかりが並んでるように見受けられます。個人的には、ゲームや動画サービスだけでなく音楽や旅行、不動産といったサービスもtvOSに向いているのではないかと思っています。これから色々なサービスがtvOSに対応してくれるのを楽しみにしております。

 

それでは、お読み頂き有難うございました。

明日クリスマスイブ、24日目の CyberAgent Developers Advent Calendar 2016 は LE VAN NGHIA さんの記事になります。お楽しみに!

 


参考文献

 

hato
2011年サイバーエージェント中途入社。 Ameba、AWAの開発を経て、現在はAbemaTVのiOS, tvOS開発を担当。