Статьи

Создание расширений SiriKit в iOS 10

Конечный продукт
Что вы будете создавать

С тех пор как Siri была представлена ​​еще в 2011 году, разработчики iOS просили предоставить ей возможность интегрировать сторонние приложения. С выпуском iOS 10 во время WWDC 2016 Apple наконец-то сделала SiriKit доступной для разработчиков. Есть все еще некоторые ограничения на то, какие типы приложений могут использовать преимущества Siri, но это шаг в правильном направлении. Давайте посмотрим, что мы можем сделать с Сири.

Чтобы узнать больше о SiriKit и других новых функциях для разработчиков под iOS 10, ознакомьтесь с курсом Маркуса Мюльбергера, прямо здесь, на Envato Tuts +.

  • IOS
    Что нового в iOS 10
    Маркус Мюльбергер

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

  • VoIP звонки (например, Skype)
  • Обмен сообщениями (WhatsApp)
  • Платежи (Квадрат, PayPal)
  • Фото (Фото)
  • Тренировки (Runtastic)
  • Бронирование поездки (Uber, Lyft)
  • CarPlay (только для автомобильных поставщиков)
  • Бронирование ресторанов (требуется дополнительная поддержка от Apple)

Если ваше приложение не относится ни к одной из этих категорий, к сожалению, вы не можете использовать Siri в своем приложении в данный момент. Не уходите пока, хотя, потому что SiriKit очень мощный, и он может получить новые возможности в будущем!

Расширение SiriKit в действительности состоит из двух типов расширений. Требуется расширение Intents которое заботится о том, чтобы обрабатывать запросы пользователя и выполнять определенную задачу в вашем приложении (например, начать вызов, отправить сообщение и т. Д.).

С другой стороны, расширение IntentsUI не является обязательным. Вы должны создать только один, если вы хотите настроить пользовательский интерфейс, который Siri показывает при представлении ваших данных. Если вы этого не сделаете, отобразится стандартный интерфейс Siri. В этом уроке мы рассмотрим оба типа расширений.

К вашему сведению, во время WWDC 2016 Apple выпустила два очень интересных видео о SiriKit. Вы можете проверить их:

Мы собираемся создать простое приложение, которое обрабатывает платежи через Siri. Цель состоит в том, чтобы успешно обработать предложение «Отправьте 20 долларов Патрику через TutsplusPayments». Формат предложения состоит из суммы денег с определенной валютой, имени получателя и приложения, которое будет использоваться для завершения транзакции. Позже мы собираемся проанализировать способ оплаты более подробно.

Давайте начнем с создания стандартного проекта Xcode в Swift и присвоения ему имени. Перед написанием любого кода необходимо выполнить несколько обязательных шагов, чтобы ваше приложение могло использовать API-интерфейсы Siri.

1. Выберите пункт Tar > Capabilities и включите функцию Siri. Убедитесь, что права были успешно созданы в структуре вашего проекта.

Просмотр возможностей проекта XCode

2. Откройте Info.plist вашего приложения и добавьте ключ NSSiriUsageDescription . Значение должно быть строкой, объясняющей использование Siri, которая будет показана пользователю при запросе начального разрешения.

3. Выберите « Файл»> «Создать»> «Цель» . В новом окне, представленном XCode, под Расширениями приложения выберите Расширение Intents . Также выберите вариант для включения расширения пользовательского интерфейса. Это избавит вас от необходимости создавать другое отдельное расширение.

Новая цель расширения Intents

В файле Info.plist вновь созданной цели Intents полностью разверните словарь NSExtension чтобы изучить его содержимое. Словарь описывает более подробно, какие намерения поддерживает ваше расширение, и хотите ли вы разрешить пользователю вызывать намерение, пока устройство заблокировано.

Вставьте наиболее релевантные намерения вверху, если вы хотите поддержать более одного. Siri использует этот порядок, чтобы выяснить, какой пользователь хочет использовать в случае неоднозначности.

Теперь нам нужно определить, какие намерения мы хотим поддержать. В этом примере мы собираемся создать расширение, которое поддерживает способ оплаты. Измените файл Info.plist чтобы он соответствовал следующей картинке.

Intents Info plist file

Здесь мы указываем, что мы хотим обработать INSendPaymentIntent и что мы требуем, чтобы устройство было разблокировано. Мы не хотим, чтобы посторонние отправляли платежи, когда устройство потеряно или украдено!

Следующим шагом фактически является написание некоторого кода в приложении для iOS. Мы должны запросить у пользователя разрешение отправить свой голос в Apple для анализа. Нам просто нужно импортировать инфраструктуру Intents и вызвать соответствующий метод следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
import UIKit
import Intents
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
        // Ask permission to access Siri
        INPreferences.requestSiriAuthorization { authorizationStatus in
            switch authorizationStatus {
            case .authorized:
                 print(«Authorized»)
            default:
                print(«Not Authorized»)
            }
        }
    }
}

Результирующий диалог, представленный пользователю во время первого запуска приложения, будет выглядеть следующим образом.

Оповещение, запрашивающее разрешение на доступ к Siri

Это все, что мы должны сделать в нашем простом приложении для iOS. Давайте войдем в мир расширений сейчас!

Переключитесь на расширение Intents которое мы создали ранее. Раскройте его содержимое в навигаторе проекта Xcode. Вы увидите только один файл с именем IntentHandler.swift .

Этот файл является точкой входа вашего расширения и используется для обработки любых намерений, которые отправляет вам Siri. Siri отправит handler(for:) метод все намерения, если ваше расширение поддерживает несколько типов. Ваша задача — проверить тип объекта INIntent и правильно его обработать.

Шаблон IntentHandler.swift уже содержит пример реализации намерения обмена сообщениями. Замените весь код следующим пустым методом, чтобы мы могли вместе пройти каждый шаг.

1
2
3
4
5
6
7
8
class IntentHandler: INExtension {
      
    override func handler(for intent: INIntent) -> Any?
        // This is the default implementation.
        // you can override this and return the handler you want for that particular intent.
        return self
    }
}

Каждое намерение имеет связанный протокол, чтобы убедиться, что класс реализует все необходимые методы. Большинство протоколов в структуре Intents имеют одинаковую структуру.

Протокол, который мы собираемся реализовать, называется INSendPaymentIntentHandling . Этот протокол содержит следующие обязательные и необязательные методы:

  • Необходимые:
    handle(sendPayment:completion:)
  • Необязательный:
    confirm(sendPayment:completion:)
    resolvePayee(forSendPayment:with:)
    resolveCurrencyAmount(forSendPayment:with:)
    resolveNote(forSendPayment:with:)

Давайте создадим расширение класса IntentHandler в том же файле Swift для реализации единственного необходимого метода.

01
02
03
04
05
06
07
08
09
10
11
12
extension IntentHandler: INSendPaymentIntentHandling {
  
    func handle(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {
        // Check that we have valid values for payee and currencyAmount
        guard let payee = intent.payee, let amount = intent.currencyAmount else {
            return completion(INSendPaymentIntentResponse(code: .unspecified, userActivity: nil))
        }
        // Make your payment!
        print(«Sending \(amount) payment to \(payee)!»)
        completion(INSendPaymentIntentResponse(code: .success, userActivity: nil))
    }
}

Это очень простая реализация. Мы уверены, что есть действующий payee и currencyAmount чтобы сделать транзакцию успешной. Вы можете не верить этому, но это уже работает! Выберите схему Intents из Xcode и запустите ее. Когда Xcode представляет обычное меню для выбора приложения для запуска, выберите Siri.

Запустите расширение в меню Xcodes

Когда Siri запускается, попробуйте сказать: «Отправьте Патрику 20 долларов через TutsplusPayments». Теперь наслаждайтесь первым успешным платежом, совершенным с вашим голосом

Первый успешный платеж через Siri

Вы также можете попробовать проверить неисправность. Попробуйте произнести то же предложение, что и раньше, но без указания получателя (т. Е. «Отправить 20 долларов через TutsplusPayments»). Вы увидите, что Siri потерпит неудачу и представит пользователю кнопку для продолжения платежа в вашем приложении.

Платеж не прошел из-за отсутствия имени получателя

В случае, если Siri не понимает или не имеет ни одного из необязательных параметров, но вам требуется допустимое значение, вы можете реализовать один из методов разрешения. Эти методы предоставляют пользователю возможность предоставить более подробную информацию о платеже, такую ​​как имя получателя, точную сумму в валюте и даже примечание. Благодаря этой интеллектуальной архитектуре API вам, как разработчику, предоставляется возможность легко и четко понимать запросы вашего пользователя по-разному.

В реальном приложении вы создадите динамическую среду, которая будет использоваться совместно вашим приложением iOS и расширениями. Используя эту архитектуру, вы можете использовать одну и ту же бизнес-логику в нескольких целях. Вам не нужно будет реализовывать это несколько раз, но только один раз и для всех целей!

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

Прежде всего, не забудьте установить правильный класс намерений, который вы хотите обрабатывать в Info.plist ExtensionUI , как мы делали в предыдущем разделе.

Перейдите в расширение Intents UI, и вы увидите шаблон, который Xcode создал для вас. Он содержит IntentViewController , который является простым подклассом UIViewController который реализует протокол INUIHostedViewControlling . Файл раскадровки был также создан для вас; откройте его, чтобы мы могли начать настройку пользовательского интерфейса.

Добавьте UIImageView в качестве фона и метку в центре. Загрузите фоновое изображение , импортируйте его в целевой объект Intents и установите как изображение вновь созданного UIImageView . Создайте объект UILabel и UILabel его в центр представления. Вы можете легко использовать AutoLayout чтобы установить ограничения в раскадровке.

Откройте помощник редактора и создайте @IBOutlet для своей метки и назовите его contentLabel . Результат должен выглядеть примерно так:

Раскадровка с новым представлением IntentsUI

Откройте файл IntentViewController и вы увидите несколько примеров кода. Вы можете удалить все, кроме configure(with:context:completion:) метода configure(with:context:completion:) который мы собираемся реализовать сейчас. Этот метод вызывается, когда пользовательский интерфейс готов к настройке. Здесь мы должны установить содержимое UILabel .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class IntentViewController: UIViewController, INUIHostedViewControlling {
      
    @IBOutlet weak var contentLabel: UILabel!
      
    // MARK: — INUIHostedViewControlling
  
    func configure(with interaction: INInteraction!, context: INUIHostedViewContext, completion: ((CGSize) -> Void)!) {
  
        if let paymentIntent = interaction.intent as?
            // If any of this properties is not set, use the default UI.
            guard let amount = paymentIntent.currencyAmount?.amount, let currency = paymentIntent.currencyAmount?.currencyCode, let name = paymentIntent.payee?.displayName else {
                return completion(CGSize.zero)
            }
            let paymentDescription = «\(amount)\(currency) to \(name)»
            contentLabel.text = paymentDescription
        }
        if let completion = completion {
            completion(self.desiredSize)
        }
    }
      
    var desiredSize: CGSize {
        return self.extensionContext!.hostedViewMaximumAllowedSize
    }
}

Прежде всего, мы проверяем, что объект intent имеет тип INSendPaymentIntent . Если это так, мы также гарантируем, что все свойства, которые мы хотим отобразить, не равны nil , в противном случае мы просто вызываем блок завершения с нулевым размером, чтобы скрыть наше пользовательское представление. Если все идет так, как мы ожидаем, мы создаем пользовательскую строку с данными, которые мы хотим показать пользователю, и устанавливаем ее как текст contentLabel .

Запустите расширение снова, и вы увидите новый вид внутри Siri!

Новый пользовательский интерфейс в расширении Siri

Сири по-прежнему показывает вид по умолчанию. Мы можем скрыть это, заставив наш контроллер представления соответствовать протоколу INUIHostedViewSiriProviding .

1
2
3
4
5
6
class IntentViewController: UIViewController, INUIHostedViewControlling, INUIHostedViewSiriProviding {
    // Previous code goes here…
    var displaysPaymentTransaction: Bool {
        return true
    }
}

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

Окончательный результат пользовательского интерфейса, отображаемого Siri

Примечание. Как видно на этом рисунке, при указании валюты, отличной от долларов США, Siri правильно понимает и возвращает код валюты в расширение. К сожалению, текст всегда отображает доллары США. Я сообщил об этой ошибке в Apple!

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

Если вы хотите узнать больше об интеграции Siri в свое приложение или если вы хотите узнать о некоторых других интересных функциях iOS 10 для разработчиков, ознакомьтесь с курсом Маркуса Мюльбергера.

  • IOS
    Что нового в iOS 10
    Маркус Мюльбергер

Кроме того, ознакомьтесь с некоторыми другими нашими бесплатными руководствами по функциям iOS 10.

  • IOS
    Обновите ваше приложение до iOS 10
    Барт Джейкобс
  • iOS SDK
    iOS 10: создание пользовательских интерфейсов уведомлений
    Дэвис Элли
  • iOS 10
    Тактильная обратная связь в iOS 10