Introducción a los Atajos de Siri
Tags: swift, ios, siri
Published: 2020-03-24 01:29:17



Hace un tiempo tuve la oportunidad de compartir con la comunidad iOS de Medellín una charla introductoria a los Atajos de Siri, una herramienta que me parece muy interesante y que para mi modo de ver no es casi implementada.

Los Atajos de Siri salieron con iOS 12 y nos permite realizar tareas diarias de forma rápida y con las apps que más usamos. Estos atajos funcionan de varias formas: 

 - Cuando son sugeridos por el propio Siri 
 - Cuando nosotros los agregamos manualmente.
 - Cuando aparecen en ciertos lugares de la aplicación.

## Atajos generados por Donaciones

Para que Siri pueda sugerir dichas acciones, nosotros como desarrolladores debemos comenzar a donarle actividades, estas actividades estarán relacionadas con el uso de la aplicación. Un ejemplo de esto podría ser una aplicación de domicilios el cual en un futuro pueda ser que Siri me sugiera comprar mi comida favorita.

Miremos cómo podemos hacer este tipo de donaciones en Swift, para esto, usaremos una aplicación básica de **Todo List**. La donación que realizaremos se hará cada vez que el usuario agregue una nueva tarea en nuestro Todo.

```swift
func  getNewTaskActivity() -> NSUserActivity {
	let activity = NSUserActivity(activityType: Constants.kNewTaskActivityType)
	activity.title = "Add a task"
	activity.isEligibleForSearch = true
	activity.isEligibleForPrediction = true
	activity.suggestedInvocationPhrase = "Let's create a task"
	
	let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
	attributes.contentDescription = "Let's add more tasks to do"
	activity.contentAttributeSet = attributes
	
	return activity
}
```
Al crear el `NSUserActivity` nos pedirá el tipo de actividad, esta será una constante con la que identificaremos la actividad que inició nuestra aplicación.

`isEligibleForSearch` permite que nuestro shortcut pueda aparecer como un resultado de búsqueda de Siri.

`isEligibleForPrediction` indica que Siri que puede sugerir esta actividad en el futuro.

Mediante `suggestedInvocationPhrase` podemos sugerirle al usuario una frase con la cual invocará la acción con Siri. En el proceso de creación del atajo, el usuario podrá modificar esta frase y usar la de su elección.

Los atributos hacen referencia a información adicional que ayudará al usuario a entender la finalidad de este atajo, esta información es opcional y para que podamos usarla debemos hacer uso de `CoreSpotlight` y `MobileCoreServices`.

Ahora, para realizar la donación utilizaremos el siguiente bloque de código:
```swift
// 1
let activity = ActivityHelper.getNewTaskActivity()
view.userActivity = activity
// 2
activity.becomeCurrent()
```
1.  Crearemos la actividad y la agregaremos al view controller que está siendo presentado
2. Llamamos `becomeCurrent()` para registrar esta actividad en el sistema.

Para ver el resultado de nuestra donación es necesario que habilitemos unas opciones de desarrollador, para esto vamos a **Configuración** buscamos **Desarrollador** y luego iremos a la sección **SHORTCUTS TESTING** en donde encontraremos `Display Recent Shortcuts` el cual nos ayudará a ver las donaciones como resultados de búsqueda en **Spotlight** y `Display Donations on Lock Screen` el cual permitirá que las donaciones aparezcan cuando tengamos la pantalla bloqueada.

![enter image description here](https://dev-to-uploads.s3.amazonaws.com/i/g46gooa8n0xdgwwwsnl0.png)

Luego de habilitar estas opciones podremos ver cómo comienzan a generarse nuestras nuevas sugerencias de Siri.

![enter image description here](https://dev-to-uploads.s3.amazonaws.com/i/lgwtuvyanab5h3fdf78i.png)

Por último, para hacer que nuestra aplicación reaccione a las acciones del atajo debemos implementar la siguiente función dentro del **AppDelegate.swift**

```swift
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
	if userActivity.activityType == Constants.kNewTaskActivityType {
		guard let navController = window?.rootViewController as? UINavigationController, let viewController = navController.viewControllers.first as? ListTableViewController else {
		return false
	}
	viewController.addTask()
	}	
	return false
}
```

Dentro de esta función validamos que la actividad que inició la aplicación corresponde a la de nuestro atajo, y por último llamamos la función `addTask()`  la cual nos llevará a la creación de las tareas.


## Atajos relevantes

Los atajo relevantes son aquellos que aparecen en lugares estratégicos de la aplicación y no es necesario esperar a que el usuario interactúe con la aplicación para que estos funcionen. Estos atajos aparecerán como un botón y se verá de la siguiente forma:

![Siri Shortcut button](https://dev-to-uploads.s3.amazonaws.com/i/4q9tvs2yipsla5mtz31l.png)

Una vez el usuario interactúe con dicho botón, automáticamente saldrá un asistente que lo guiará en la configuración del atajo.

![Siri Shortcut wizard](https://dev-to-uploads.s3.amazonaws.com/i/sabndzhxarlt2upbwspf.png)

Para agregar este botón vamos a hacer uso de la librería `IntentsUI`. El siguiente código de ejemplo es utilizado para agregar el botón a la vista de forma programática.

```swift
lazy  var  shortcut: INUIAddVoiceShortcutButton = {
	// 1
	let activity = ActivityHelper.getNewTaskActivity()
	// 2
	let shortcut = INShortcut(userActivity: activity)
	// 3
	let button = INUIAddVoiceShortcutButton(style: .whiteOutline)
	button.shortcut = shortcut
	button.translatesAutoresizingMaskIntoConstraints = false
	// 4
	button.delegate = self

	return button
}()
```
1. Obtenemos la actividad que será utilizada dentro de este atajo, para este ejemplo utilizaremos la actividad generada anteriormente que es `getNewTaskActivity()`.
2. Una vez tenemos esta actividad procedemos a generar un nuevo shortcut a través de la clase `INShortcut`, el cual recibe como parámetro nuestra actividad recientemente creada.
3. Por último creamos el botón que utilizaremos en nuestra vista a través de la clase `INUIAddVoiceShortcutButton` y le asignaremos el atajo que creamos en el paso anterior.
4. Es necesario implementar `INUIAddVoiceShortcutButtonDelegate` para responder a las posibles acciones del botón. Este delegate tienes dos métodos que son importantes para nosotros: `addVoiceShortcutViewController` y `editVoiceShortcutViewController`. Para nuestro ejercicio solo utilizaremos el primero.

`addVoiceShortcutViewController` es llamado cuando el usuario va a crear un nuevo atajo, y es necesario que implementemos `INUIAddVoiceShortcutViewControllerDelegate` para conocer el resultado del proceso de creación. Estos resultados podrán ser `addVoiceShortcutViewController` y `addVoiceShortcutViewControllerDidCancel`.

El siguiente bloque de código nos muestra la implementación de los dos delegates anteriores.

```swift
extension  TaskItemViewController: INUIAddVoiceShortcutButtonDelegate {
	func present(_ addVoiceShortcutViewController: INUIAddVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {
		addVoiceShortcutViewController.delegate = self
		present(addVoiceShortcutViewController, animated: true)
	}

	func present(_ editVoiceShortcutViewController: INUIEditVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {

	}
}

extension  TaskItemViewController: INUIAddVoiceShortcutViewControllerDelegate {
	func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
		controller.dismiss(animated: true)
	}

	func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
		controller.dismiss(animated: true)
	}
}
```

Una vez creado el atajo, podremos acceder a él a través de la aplicación Atajos del iPhone.

![Shortcuts App](https://dev-to-uploads.s3.amazonaws.com/i/6qe6qa83gkk6jiah3xup.png)

Si quieres probar esta implementación puedes acceder a este repositorio de Github y clonar el proyecto.

{% github AndresR173/sirikit-demo no-readme %}