Site icon AppTractor

Делаем первый App Shortcut

В iOS 16 компания Apple запустила фреймворк App Intents, позволяющий разработчикам легче интегрировать действия своих приложений в систему. Действия приложений могут использоваться в различных частях системы, таких как виджеты, приложение Shortcuts, Siri и Spotlight. До появления фреймворка App Intents мы использовали SiriKit для передачи наших действий в систему, но эта платформа имела более высокий барьер для входа из-за недостатка документации и ресурсов.

Одна из моих любимых особенностей создания действий приложения с помощью App Intents — простота создания прототипов. Я могу пройти путь от идеи до работающего действия менее чем за час. В этом руководстве я расскажу вам о том, как создать первое действие для приложения Shortcuts.

Созданное нами действие будет доступно системе при первой установке нашего приложения и сразу же станет доступно Siri. Однако в данном руководстве мы не будем рассматривать взаимодействие между действием и Siri — мы сосредоточимся на том, как пользователь может использовать ваше действие в Shortcuts.

Прежде чем начать, давайте рассмотрим, что нам нужно сделать для создания простого ярлыка:

  1. Соответствовать протоколу AppIntent.
  2. Добавить описание
  3. Добавить параметр(ы)
  4. Обработать пользовательский ввод в методе perform

Соответствие протоколу AppIntent

Начните с соответствия протоколу AppIntents. Это можно сделать, присвоив действию название, а затем добавив метод perform.

import AppIntents

struct AddTaskIntent: AppIntent {

  static var title: LocalizedStringResource = "Add task"

  func perform() async throws -> some IntentResult {
    return .result()
  }
}

Здесь:

Если вы хотите открыть приложение после выполнения действия, установите свойство openAppWhenRun в true.

Первая задача выполнена!

Добавление описания

Описание говорит нам о цели интента — это необязательное свойство, но мы добавим его сюда в качестве следующего шага.

import AppIntents

struct AddTaskIntent: App Intent {

  static var title: LocalizedStringResource = "Add task"
  static var description: IntentDescription? = "This action allows you to add a new task to your to-do list "

  func perform() async throws -> some IntentResult {
    return .result()
  }
}

Добавление параметров

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

import Foundation
import AppIntents

struct AddTaskIntent: App Intent {

  @Parameter(title: "Task")
  var task: String

  static var title: LocalizedStringResource = "Add task"
  static var description: IntentDescription? = "This action allows you to add a new task to your to-do list "

  func perform() async throws -> some IntentResult {
    return .result()
  }
}

Мы можем добавить другие свойства в обертку свойства параметра, например:

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

import Foundation
import AppIntents

struct AddTaskIntent: App Intent {

  @Parameter(title: "Task")
  var task: String

  static var title: LocalizedStringResource = "Add task"
  static var description: IntentDescription? = "This action allows you to add a new task to your to-do list "

  static var parameterSummary: some ParameterSummary {
    Summary("Add \(\.$task)")
  }

  func perform() async throws -> some IntentResult {
    return .result()
  }
}

В данном примере при запуске ярлыка отображается текстовое поле. Нажатие кнопки «Готово» приводит к его удалению, но дальнейшего взаимодействия не происходит.

В зависимости от наличия знака ? система рассматривает параметр как обязательный или нет. Если вы не добавите знак ?, система предложит пользователю ввести параметр — при наличии знака ? система продолжит выполнение действия. Если вы хотите запросить значение параметра, используйте .needsValueError() с диалогом, который вы хотите, чтобы система использовала для запроса пользователя.

needsValueError(_:) Возвращает ошибку restartPerform с контекстом для запроса у пользователя значения этого параметра и повторного выполнения намерения с новыми значениями. — Apple

import Foundation
import AppIntents

struct AddTaskIntent: App Intent {

  @Parameter(title: "Task")
  var task: String

  static var title: LocalizedStringResource = "Add task"
  static var description: IntentDescription? = "This action allows you to add a new task to your to-do list "

  static var parameterSummary: some ParameterSummary {
    Summary("Add \(\.$task)")
  }

  func perform() async throws -> some IntentResult {
    guard let task = task else {
      throw $task.needsValueError("What task would you like to add?")
    }
    return .result()
  }
}

Обработка пользовательского ввода в методе perform

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

import Foundation
import AppIntents
import SwiftUI

struct AddTaskIntent: App Intent {

  @Parameter(title: "Task")
  var task: String

  static var title: LocalizedStringResource = "Add task"
  static var description: IntentDescription? = "This action allows you to add a new task to your to-do list "

  static var parameterSummary: some ParameterSummary {
    Summary("Add \(\.$task)")
  }

  private let persistenceController: PersistenceController = .shared

  @MainActor
  func perform() async throws -> some ShowsSnippetView {
    try persistenceController.addTask(Task(title: task, createDate: .now))
    return .result(view: Text("Task added successfully"))
  }
}

Метод perform выполняется, когда система разрешила все параметры, необходимые вашему коду для успешного выполнения его функциональности. При реализации задач в методе perform добавляемая логика должна выполнить необходимую работу, которая вернет системе нужное значение. Таким результатом может быть значение, которое шорткат может использовать в последующих связанных действиях, диалог для отображения, представление сниппета SwiftUI и т.д. Если интенту нет смысла возвращать конкретный результат, верните .result(), чтобы сообщить системе о завершении намерения.

Если намерение манипулирует пользовательским интерфейсом приложения, аннотируйте perform() с помощью @MainActor, чтобы убедиться, что функция выполняется в главной очереди. — Apple

Примечание: Когда мы указываем значения, возвращаемые из метода perform:

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

Источник

Exit mobile version