AppIntents, disponible desde iOS 16, es el framework de Apple para exponer funcionalidades de tu app a Shortcuts, Siri y el sistema de acciones rápidas. Sustituye al antiguo SiriKit con un modelo declarativo mucho más flexible: cualquier función de la app se puede convertir en un intent en pocas líneas.
Crear un intent básico: AppIntent
Un intent es una estructura que conforma el protocolo AppIntent. El requisito mínimo es un title y el método perform():
import AppIntents
struct AbrirTareaIntent: AppIntent {
static var title: LocalizedStringResource = "Abrir tarea"
static var description = IntentDescription("Abre una tarea específica de la app.")
func perform() async throws -> some IntentResult {
// Navegar a la lista de tareas
return .result()
}
}
Para parámetros, usa el wrapper @Parameter:
struct CrearTareaIntent: AppIntent {
static var title: LocalizedStringResource = "Crear tarea"
@Parameter(title: "Título de la tarea")
var titulo: String
@Parameter(title: "Fecha límite")
var fechaLimite: Date?
@Parameter(title: "Prioridad", default: .media)
var prioridad: Prioridad
func perform() async throws -> some IntentResult & ProvidesDialog {
let tarea = TareaManager.shared.crear(
titulo: titulo,
fecha: fechaLimite,
prioridad: prioridad
)
return .result(dialog: "Tarea '(tarea.titulo)' creada.")
}
}
@Parameter con tipos personalizados
Para que los parámetros acepten tipos de tu app en Shortcuts, el tipo debe conformar AppEnum (para enumeraciones) o AppEntity (para entidades con búsqueda):
enum Prioridad: String, AppEnum {
case alta, media, baja
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Prioridad"
static var caseDisplayRepresentations: [Prioridad: DisplayRepresentation] = [
.alta: "Alta",
.media: "Media",
.baja: "Baja",
]
}
AppShortcutsProvider: atajos predefinidos
Los AppShortcut son atajos que aparecen automáticamente en Shortcuts sin que el usuario los configure manualmente. Se definen en un AppShortcutsProvider:
struct MiAppShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: CrearTareaIntent(),
phrases: [
"Crear tarea en (.applicationName)",
"Nueva tarea con (.applicationName)",
],
shortTitle: "Crear tarea",
systemImageName: "plus.circle"
)
AppShortcut(
intent: MostrarTareasPendientesIntent(),
phrases: [
"Ver tareas pendientes en (.applicationName)",
"Qué tareas tengo en (.applicationName)",
],
shortTitle: "Tareas pendientes",
systemImageName: "checklist"
)
}
}
Las frases con (.applicationName) son obligatorias en al menos una frase por shortcut para que Siri pueda activarlos con el nombre de la app.
EntityQuery: seleccionar entidades en Shortcuts
Para que el usuario pueda elegir una entidad concreta de tu app (por ejemplo, una tarea específica), implementa AppEntity y EntityQuery:
struct TareaEntity: AppEntity {
let id: UUID
let titulo: String
let completada: Bool
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Tarea"
static var defaultQuery = TareaQuery()
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "(titulo)")
}
}
struct TareaQuery: EntityQuery {
func entities(for identifiers: [UUID]) async throws -> [TareaEntity] {
TareaManager.shared.tareas
.filter { identifiers.contains($0.id) }
.map { TareaEntity(id: $0.id, titulo: $0.titulo, completada: $0.completada) }
}
func suggestedEntities() async throws -> [TareaEntity] {
TareaManager.shared.tareasPendientes()
.prefix(5)
.map { TareaEntity(id: $0.id, titulo: $0.titulo, completada: $0.completada) }
}
}
struct CompletarTareaIntent: AppIntent {
static var title: LocalizedStringResource = "Completar tarea"
@Parameter(title: "Tarea")
var tarea: TareaEntity
func perform() async throws -> some IntentResult & ProvidesDialog {
TareaManager.shared.completar(id: tarea.id)
return .result(dialog: "'(tarea.titulo)' marcada como completada.")
}
}
ControlWidget en iOS 18
iOS 18 añade los Controls al Centro de Control. Usan la misma API de AppIntents:
import WidgetKit
struct ControlActivarModoFoco: ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(
kind: "com.miapp.foco",
provider: ProveedorFoco()
) { value in
ControlWidgetToggle(
"Modo Foco",
isOn: value,
action: ActivarFocoIntent()
) { isOn in
Label(isOn ? "Foco activo" : "Foco inactivo",
systemImage: isOn ? "moon.fill" : "moon")
}
}
}
}
Errores frecuentes
El error más habitual al empezar con AppIntents es olvidar añadir la extensión de Shortcuts al target en Xcode. Los intents deben estar en el target principal de la app, no solo en el target de extensión. Otro error es no incluir (.applicationName) en alguna frase del shortcut: Siri lo requiere para poder activar el shortcut por voz.
Resumen
AppIntents moderniza la integración de apps iOS con Shortcuts y Siri. Un AppIntent con @Parameter expone funciones de la app; AppShortcutsProvider define atajos listos para usar sin configuración; AppEntity y EntityQuery permiten seleccionar objetos propios de la app en los flujos de Shortcuts; y los ControlWidget de iOS 18 llevan los intents al Centro de Control. La curva de aprendizaje es baja en comparación con el antiguo SiriKit y el resultado es notablemente más potente.
