[iOS 10] Встраиваем поддержку Siri в свое iOS приложение

image

Apple показала на WWDC 2016 новые iOS 10 и macOS Sierra, и я не упустил возможность сразу же обновить свои устройста.

Одно из ключевых обновлений — появление SiriKit для разработчиков, теперь у нас с вами есть возможность использовать Siri в собственных приложениях. И мы сегодня сделаем наше первое приложение с поддержкой Siri (исходники проекта в конце статьи)

(!) Уважаемые читатели «Хабрахабра», все ошибки и правки по данной статье присылайте, пожалуйста, в личные сообщения.

Мои впечатления от iOS 10 и macOS


В новой macOS появилась Siri — это сразу бросается в глаза, с новыми функциями. Наконец-то заработал обмен ссылками между iOS и macOS — как только открываешь страницу на iPhone/iPad — сразу появляется на mac значек Safari, открывающий эту страницу (Раньше эта функция работала через раз). Ну и конечно очень круто — что копируя текст на iOS — его можно вставить на macOS. С картинками и фото тоже самое — один клик на iPhone, и фото уже на ноутбуке, больше не нужно мэйлить фото самому себе. По умолчанию включается на macOS телеметрия, которую я сразу отключил (скрин). Из минусов iOS 10 — действительно тормозная, иногда (не всегда) на iPhone 5S и iPad Air подтормаживает скролл, но в целом, интерфейс выглядит более стильно, контрастнее, изменения UI незначительные, но в целом «более стильно и минималистично» :) В плане UI дизайна так же стоит отметить обновленные формочки для IN-APP уведомлений.

image

Apple предлагает несколько сценариев для использования Siri сторонними разработчиками:

  • Аудио и видео звонки
  • Работа с сообщениями и контактами
  • Совершение платежей с помощью Siri
  • Поиск фотографий
  • Тренировки
  • Работа с картами (Вызов такси)

В данной статье я покажу, как создавать StoryBoard интерфейс для Siri и вызывать наши функции с помощью голосового помощника.

Для начала скачиваем и устанавливаем Xcode 8 и создаем новое приложение с одним ViewController и называем его, например «DemoApp».

Для добавления голосовой поддержки нам придется добавить новое расширение, для этого выбираем в левой панели файлового менеджера верхнюю строчку (файл проекта) и выбираем в меню Editor → Add target…

image

Назовем наше расширение «DemoAppSiriIntent», так же не забываем проверить наличие галочки напротив «Include UI Extension»

image

Так же для работы Siri нам необходимо добавить в проект библиотеку CoreLocation.framework

image

У нас в проекте появились новые файлы

  • IntentHandler.m — файл с CallBack функциями, которые возвращает Siri
  • IntentViewController.m — файл для работы с StoryBoard интерфейсом, который расположен рядом, в файле MainInterface.storyboard

Для начала мы научим наше приложение запускать «Фитнес активность» (Workout), для этого в файле IntentHandler.m должны быть объявленны следущие Delegates:

@interface IntentHandler () 
@end

Для обозначения методов взаимодействия с Siri Apple использует слово «Intent», теперь, зажимая клавишу CMD, кликаем на «INStartWorkoutIntentHandling» и смотрим, какие функции использует данный deligate.

Обязательный для включения в проект метод:

  • handleStartWorkout

Дополнительные методы, которые можно не включать в проект:

  • confirmStartWorkout
  • resolveWorkoutNameForStartWorkout
  • resolveGoalValueForStartWorkout
  • resolveWorkoutGoalUnitTypeForStartWorkout
  • resolveWorkoutLocationTypeForStartWorkout
  • resolveIsOpenEndedForStartWorkout

Медод «confirmStartWorkout» вызывает по порядку следущие Callback функции, которые уже автоматически созданы в нашем файле «IntentHandler.m»:

  • resolveWorkoutNameForStartWorkout
  • resolveGoalValueForStartWorkout
  • DemoAppSiriIntent
  • resolveWorkoutLocationTypeForStartWorkout
  • resolveIsOpenEndedForStartWorkout
  • confirmStartWorkout
  • handleStartWorkout

Рядом с файлом «IntentHandler.m» мы видим plist с настройками нашего «Intent» расширения, «Info.plist».

Проверяем, что в ветке »NSExtension → NSExtensionAttributes → IntentsSupported» перечислены все наши Intents для работы с Siri Workout:

  1. Item 0: INStartWorkoutIntent
  2. Item 1: INPauseWorkoutIntent
  3. Item 2: INResumeWorkoutIntent
  4. Item 3: INCancelWorkoutIntent
  5. Item 4: INEndWorkoutIntent

image

Если мы продублируем данные «Intents» в ветку »NSExtension → NSExtensionAttributes → IntentsRestrictedWhileLocked», то Siri сможет вызывать функции из нашего приложения даже с заблокированного устройства.

Теперь переходим к файлу «MainInterface.storyboard» и для демо приложения добавляем на него два UILabel, один из них будет счетчиком, для демонстрации того, что наш UI интерфейс внутри Siri может обновляться в реальном времени.

image

Важно отметить, что данный интерфейс не может содержать «gesture recognizers» и перехватчики событий нажатия пальцами и, при закрытии данного окна, Siri освободит все объекты в памяти.

На следующей схеме мы можем ознакомиться с жизненным циклом нашего «Siri view интерфейса».

image

Итак, самое время скомпилировать наше приложение и проверить, работают ли голосовые команды. Тестировать данный пример получится только на реальном устройстве, для начала собираем приложение как обычно:

image

Затем нажимаем на Stop и отдельно компилируем наше расширение, выбрав схему «DemoAppSiriIntent». Во время компиляции Xcode спросит нас, для какого приложения мы собираем данное расширение, и в списке мы указываем «DemoApp».

image

На этом этапе мы увидим, что наше приложение появляется на секунду и тут же исчезает, это не «вылет», всё функции вывода NSLog из файла «IntentHandler.m» показывают нам, что все работает.

Ах да, чуть не зыбыл, в настройках нашего iOS девайса заходим в раздел Siri и устанавливаем галочку напротив нашей программы «DemoApp»:

image

Итак, самое время произнести вслух «Hey, Siri, start workout in DemoApp»

Результат вы можете наблюдать на данном видео:

Теперь мы убедились, что все работает, давайте добавим поддержку сообщений в наше приложение.

Перейдя по данной ссылке, вы можете ознакомиться со всеми «Intent» методами, которые поддерживаются в данный момент Siri:
https://developer.apple.com/…

Сейчас нас интересует секция «Messaging», открываем наш «IntentHandler.m» файл, прописываем delegate для сообщений:

@interface IntentHandler () 

Удерживая зажатой CMD — кликаем на «INSendMessageIntentHandling» и видим, что необходимой функцией в этот раз является «handleSendMessage». Для начала присваиваем «Intent» для сообщений в функции «handlerForIntent»:

- (id)handlerForIntent:(INIntent *)intent {
    id handler = nil;
    if ([intent isKindOfClass:[INSendMessageIntent class]]) {
        handler = self;
    }
    handler = self;
    return handler;
}

И затем пишем callback функцию для нашего «Intent»:

- (void)handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse * _Nonnull))completion {
    NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
    INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:
        INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
    NSLog(@"handleSendMessage");
    completion(response);
}

Не забываем прописать наш новый «Intent» в plist.info, в ветку »NSExtension → NSExtensionAttributes → IntentsSupported»:

image

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

Исходные файлы проекта из данной статьи вы можете скачать по ссылке:

http://big-lab.com/images/articles/sirikit/DemoApp.zip

© Habrahabr.ru