Все знают, что еще в сентябре Apple представила Apple TV четвертого поколения с новой операционной системой tvOS на борту, и что для него можно разрабатывать свои приложения. О том, как это делать, уже кое-что писали, и в этой статье мы тоже обратимся к этой теме. О чем необходимо знать, приступая к разработке под tvOS и как избежать некоторых сложностей?

Изменилось взаимодействие между приложением и пользователем


Раньше мы могли прикоснуться к экрану, нажать на кнопку, перелистнуть картинку — работали с интерфейсом напрямую. Теперь взаимодействие происходит опосредованно, у пользователя есть два способа взаимодействия:
  1. Через пульт управления
  2. Управление при помощи Siri


Пульт управления тоже обновился, теперь там есть:
  1. Тач панель (можно тапать, свайпать и т.д.)
  2. Кнопка меню
  3. Siri
  4. Микрофон
  5. Play/Pause
  6. Домой
  7. Громкость
  8. Гироскоп
  9. Отверстие для зарядки


Также Пульт можно использовать как джойстик для игр. А еще Apple предоставила возможность подключать сторонние джойстики и написала инструкцию, как обеспечить работу своего джойстика.
Но что значит для команды разработки взаимодействие через пульт? Значит это то, что пользователю нужно давать понять, на каком элементе управления он находится и на что может нажать в каждый конкретный момент. Для это сделано такое средство как Focus. Focus говорит о том, что в одно и то же время в фокусе может находиться один и только один элемент.



UIKit framework поддерживает только интерфейсы, которые поддерживают работу с Focus. Другими словами, для большинства элементов Focus работает “из коробки”. Программно Focus можно только заставить обновиться, но установить или передвинуть его программно нельзя.
Что значит в большинстве случаев? Например, UIButton поддерживает фокус. На нее можно нажать.UILlabel Focus не поддерживает, на лейбл нельзя нажать — да и зачем? По умолчанию Focus поддерживают следующие UI-элементы:
  • UIButton
  • UITextField
  • UITableView
  • UICollectionView
  • UITextView
  • UISegmentedControl
  • UISearchBar

Об обновлении Focus более подробно написано в документации.

Домашний экран Apple TV теперь выглядит по-новому





TOP SHELF


Теперь он состоит из иконок приложения и Top Shelf (опционально), который располагается над иконкой приложения. Когда пользователь выбирает ваше приложение (фокусируется ), над иконкой появляется Top Shelf.
Top Shelf – некое подобие виджета, если проводить паралели с iOS.



Top Shelf отличное место, чтобы продемонстрировать ключевой контент вашего приложения (например, погода) или сделать шорткат для пользователя, например, вернуть его к просмотру фильма, который поставлен на паузу.
Для вашего приложения Top Shelf является расширением (extension). Специально для работы с ним написан новый фреймворк – TV Services framework, который состоит из:
Объекта TVContentIdentifier – уникальный идентификатор медиаконтента
Объекта TVContentItem – любой из элементов или контейнер для элементов, отображаемых в Top Shelf
Протокола TVTopShelfProvider с двумя обязательными для реализации методами
topShelfItems – возвращает элементы, которые должны быть отображены в Top Shelf
topShelfStyle – говорит о том, какой стиль использовать для отображения элементов

Добавление Top Shelf в tvOS application-проект



Для того чтобы добавить Top Shelf в проект, необходимо:

  1. Добавить новый target в ваш проект.
    File > New > Target
  2. Выбирать TV Service Extention
    tvOS > Application Extention > tvOS > Application Extention
  3. Дать имя для вашего Top Shelf
  4. Согласиться активировать схему Top Shelf для отладки
  5. В проекте появится папка с вашим только что созданным Top Shelf




Ну а дальше дело техники — выбираем стиль отображения TopShelf и добавляем необходимые элементы. Варианты реализации можно посмотреть в примере проекта от Apple.

Параллакс



Иконка тоже не такая простая, как кажется. Все иконки в tvOS должны поддерживать параллакс.





Apple разработала для параллаксных картинок новый формат файла – .lsr
Параллакс достигается многоуровневым наложением картинок, такие картинки можно создавать либо прямо из Xcode, либо из специальной удобной программы Parallax Previewer, другой альтернативный вариант — скачать расширение для Photoshop. В архиве вместе с расширением для Photoshop есть инструкция по работе.





Два способа разработки: TVML vs нативное приложение



Каждый из них имеет свои преимущества и недостатки.

1. TVML

Первый способ предполагает использование стека технологий TVML, TVJS и TVMLKit
  • TVML – Television Markup Language – родственник XML
  • TVJS – набор JavaScript API, который обеспечит создание интерфейса приложения
  • TVMLKit – клей между TVML, JavaScript и приложением для tvOS

И чтобы нам было проще, Apple подготовила для нас инструкции и каталог шаблонов,
Плюс: Приложение можно обновлять, обновляя свой сервер. Больше вам не придется ждать ревью в аппсторе!
Минус: Слабо кастомизируется. Нативные приложения всегда будут выглядеть лучше.
Вообще, это отличное решение типичного юскейса для приложения на Apple TV. Допустим, у вас уже есть сервер, который предоставляет видеоконтент для пользователей, и вы не хотите заморачиваться с дизайном или сложной навигацией для вашего tvOS-приложения. В таком случае разработка приложения с помощью TVML подойдет вам идеально.

2. Нативное приложение

В этом случае процесс разработки под Apple TV практически идентичен созданию обычных iOS-приложений, здесь также можно использовать Objective-С и/или Swift. Большинство iOS-фреймворков доступны и для tvOS, среди них MediaPlayer или UIKit. Полный список можно найти тут.

Ограничения


Нет локального хранилища данных. Для хранения приходится использовать iCloud, CloudKit или свой собственный бэкэнд.
Размер приложения не должен превышать 200 Мб.

Авторизация


Отдельно хотелось рассказать про проблемы с авторизацией. Сейчас ввод пароля выглядит примерно так:





Авторизация требуется довольно часто, например, при покупке фильма или загрузке приложения, даже бесплатного. Довольно скоро такой способ авторизации покажется утомительным. Поэтому если в вашем приложении присутствует авторизация, стоит задуматься о том, как сделать ее менее болезненной. В сети уже можно найти несколько примеров интересных решений (1, 2), но никто не запрещает пофантазировать дальше и попробовать использовать для авторизации QR-коды, Siri (“сим-сим-откройся”) или тач-панель пульта для ввода графического кода (как в Android).

Ссылки


  1. Документация Apple
  2. Downloads for tvOS
  3. Примеры – туториалы – семплы
  4. Авторизация
  5. Другое

Комментарии (3)


  1. InstaRobot
    07.04.2016 14:59

    Все знают, что еще в сентябре Apple представила Apple TV третьего поколения…

    А не четвертого разве?


    1. zhorkov023
      07.04.2016 15:00

      Действительно четвертого. Спасибо! Поправил.


  1. Makaveli
    08.04.2016 11:56

    Довольно скоро такой способ авторизации покажется утомительным.

    Но можно подключить iPhone как ещё один пульт через приложение Пульт ДУ и вводить пароль с экранной клавиатуры. Кроме того, в последних версиях TV OS добавили возможность подключения Bluetooth-клавиатур. Хотя мне больше нравится вариант с телефоном, т.к. держать отдельную клавиатуру для теле-преставки как-то странно.

    Программно Focus можно только заставить обновиться, но установить или передвинуть его программно нельзя.

    Как раз через «заставить обновиться» его и можно передвинуть.

    Вызываем setNeedsFocusUpdate() и переопределяем preferredFocusedView:
    override var preferredFocusedView: UIView? {
    	return self.episodesCollectionView
    }
    


    Так же есть методы для UICollectionView в протоколе его Data Source:
    func collectionView(collectionView: UICollectionView, didUpdateFocusInContext context: UICollectionViewFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    	// смотрим на context.nextFocusedView и context.previouslyFocusedView, 
    	// понимаем, например, что только что перешёл фокус на наш CollectionView, ищем какой indexPath выделить
    	self.firstUnwatchedEpisodeIndexPath = NSIndexPath.init(forRow: index, inSection: section)
    	collectionView.setNeedsFocusUpdate()
    }
    
    func indexPathForPreferredFocusedViewInCollectionView(collectionView: UICollectionView) -> NSIndexPath? {
    	return self.firstUnwatchedEpisodeIndexPath
    }