Ålonelybytes— one more developer

Приложение для Apple Watch за час

Apple Watch вот-вот появится у миллионов людей по всему миру. Разработчики готовятся к этому знаменательному событию, адаптируют свои приложения, сталкиваются с проблемами, решают их.

Мы с Ильёй не планировали делать ничего для Ангстрема. Вместо этого сосредоточились на стабилизации того, что есть, написании тестов, и продумывании некоторых моментов, которые оказались менее крутыми, чем мы думали изначально. Но Ангстрем — это «проект выходного дня», на основной работе потребовалось изучить на примерах, что же может Apple Watch. Я решил, что стоит попробовать сделать это на примере Ангстрема.

Задача была — разобраться с базовыми вещами:

Ангстрем подошел идеально из-за того, что в нём поддерживается диктовка. Собственно, это единственный способ ввода текста на Apple Watch, помимо закодированных заранее строк. Осталось только прикрутить её к часам.

Создание и настройка проекта

В теории всё просто. Добавляем таргет WatchKitApp в проект, их появляется два (WatchKit Extension, WatchKit Application), и должно работать. На деле оказалось, что Xcode не успевает за новыми железками и бета-версия 6.3, которую я тогда использовал, не умеет собирать приложения WatchKit, пришлось немного погуглить, поправить руками файл проекта.

В дальнейшем, разбираясь со сборкой проекта, я нашел еще несколько важных моментов:

Разобравшись с проектом и запустив приложение, получив черный экран, я пошел разбираться с интерфейсом.

Интерфейс приложений для Apple Watch  

 

Разрабатывается интерфейс в том же Xcode при помощи привычных сторибоардов. Возможностей, правда, сильно меньше и компоненты совершенно другие, лейаут другой. Я делал только экран самого приложения, глэнсы и нотификации не трогал.

Вот, например, как выглядят настройки компонента «Image», работающего с картинками и покадровой анимацией.  

 

Сверху все просто, а разделы Position и Size — это как раз новый лейаут. Position определяет, куда этот компонент будет «стремиться». Если все компоненты по-вертикали позиционируются сверху, то получится вот так (они накидываются в скролл-вью сверху вниз):  

 

А если в поле «позиция» прописать «Bottom», то вот так:  

 

Можно, например, комбинировать, что-то прибить к верху, что-то к низу.  

 

Поле «Размер» — отвечает за размер в соответствующем направлении. Есть три типа:

Например, чтобы расставить вьюшки наверх и вниз, чтобы верхняя занимала 0.2 высоты, а нижняя — 0.7, а между ними была дырка, нужно выставить значения как-то так:

Adjustments позволяет «дотюнить» позицию до нужной в случае необходимости.

Как только понимаешь значения каждого из этих параметров, остальное становится достаточно просто. Сложные интерфейсы делаются тут при помощи вложения контейнеров в другие контейнеры.

Остальные моменты проще посмотреть в официальном документе.

Код

Почему вообще Apple Watch требует два (а с основным — три) таргета? Всё просто:

Для меня было три момента, с которыми нужно было разобраться: - как получить от пользователя ввод (в какой-нибудь форме) и - как сконвертировать ввод пользователя - как вернуть и отобразить результат обратно

Первый пункт Эпл решила за меня. Ввод на часах доступен только при помощи диктовки или заранее подготовленных строк. Заранее ничего подготовить я не могу, поэтому оставался единственный вариант, диктовка.

Расчеты удалось (в отличие от тудей-екстеншна) провести в основном приложении, которое всё уже умеет. Делается это при помощи метода openParentApplication:reply: который как принимает NSDictionary значений, так и возвращает. Единственный важный момент заключается в том, что все значения должны нормально сериализовываться. Строки, числа, NSData — будут переданы отлично. Кастомные классы — только после соответствующей подготовки.

С возвращением (помимо того, что NSAttributedString напрямую передавать нельзя) возникли проблемы. Хотелось сделать красиво, с правильными шрифтами, отступами. Илья нарисовал красивый дизайн… В результате я отказался от вывода результата при помощи NSAttributedString, как хотел изначально. Это бы потребовало добавления нескольких шрифтов на часы и сложной многопроходной логики редеринга результата. Более простым решением оказалось создавать картинки на Айфоне, которые уже передавать.

Это решение оказалось удобным ещё и для тестирования. Я написал небольшую подпрограмму, которая выводит много разных результатов в картинки, чтобы мы с Ильёй смогли проверить красоту. Проверяли, отсматривая вот такие простыни картинок (2 языка, 2 размера экрана часов, больше тысячи картинок для каждого).

Всё остальное оказалось делом техники. Конечно же, пришлось потратить несколько часов на то, чтобы улучшить само распознавание наговоренного человеком текста, но в остальном, приложение не потребовало от меня больших затрат. Основа была сделана, как я и написал в заголовке, за час. Я написал несколько десятков строчек кода, а остальное время разбирался с нюансами, API, HIG и тому подобным.

Отладка приложения в симуляторе

Отлаживать на устройстве не получилось по очевидной причине, нет устройства. Симулятор тоже работает странно (нужно выбрать в «дополнительных экранах» нужный размер экрана вотча, он появится вторым окном в симуляторе). Нет ни хоум-скрина, не работает диктовка (пришлось исхитряться), брякпоинты работают через раз (таргетов три, нужно понимать, к какому процессу подключаться для отладки той или иной фичи) и так далее.

Поэтому я всю основную работу делал в приложении. Сэмулировал вызов нужного метода, получал и проверял результат. Поскольку интерфейс с часами очень простой (туда строка, размер экрана, обратно — картинка), то и сделать это оказалось достаточно просто.

Сборка приложения

Кроме создания приложения нужно его выложить. За сборку всех приложений у меня отвечает моя собственная система, Bilt, которая умеет готовить приложение для AdHoc или AppStore распространения, выкачивать провижн-профайлы, встраивать Fabric, прописывать правильные версии и дополнительные параметры, упрощающие в дальнейшем анализ ошибок, и вкачивать все это либо в Fabric, либо в iTunesConnect.

Эта система никак не хотела собирать и вкачивать приложение. Добраться до источника проблемы получилось на закрытых Apple-форумах, где выяснилось, что xcodebuild, которым производится сборка, не умеет делать ipa-файлы с поддержкой Apple Watch. И нужно либо руками прописывать там хитрую структуру каталогов, либо не париться и воспользоваться Xcode, в котором кнопка «отправить в AppStore» работает. Поэтому вся подготовительная работа у меня делается Bilt’ом, а потом полученный archive-файл я открываю в Xcode и завершаю отправление приложения в стор. Надеюсь, что xcodebuild допилят и все станет хорошо.

Проблемы со шрифтами

Шрифты — то, с чем пришлось повозиться, потому что хотелось и красиво и «как принято в Apple Watch», то есть, новой гарнитурой, Сан-Франциско.

Выяснилось, что в Сан-Франциско нет русских букв, вместо них подставляется Гельветика. В экранном варианте шрифта нет также и курсива. С некоторыми символами происходят странные трансформации. Так, µ, к примеру, становится курсивной.

Пришлось придумать десяток хитростей, чтобы нивелировать все эти мелочи и стало хорошо.

Результат

Получилась магия. Я, тестируя обычной диктовкой на Айфоне, радуюсь, как ребенок. Говоришь ему «New York», он показывает текущее время в Нью-Йорке.

У меня английский UI на Айфоне, поэтому доступна только ASCII-клавиатура и только английская диктовка. Мне так приятнее. Отстутствие лишних клавиатур также сильно ускоряет ввод, не нужно их постоянно переключать. Запустил, ввел пару букв латиницей и получил результат.

Или говоришь ему «6 feet 2 inches», чтобы узнать, какой рост у Стива Джобса в понятных величинах, а Ангстрем такой: «6,1666666 ft = 1,88 m». Или «UK Pound rate», или «how many cups in a liter», или «twelve hundred in Tokyo», или «3 ångström». И оно понимает!

Магия!

apple watch angstrom