# App Intents und Siri Shortcuts: fortgeschrittene iOS-Automatisierung 2026 > Vollständiger Leitfaden zu App Intents und Siri Shortcuts für iOS 18+. Eigene Siri-Aktionen erstellen, Apple Intelligence integrieren und die Swift-App 2026 automatisieren. - Published: 2026-03-08 - Updated: 2026-04-29 - Author: SharpSkill - Tags: app-intents, siri-shortcuts, ios, swift, apple-intelligence - Reading time: 15 min --- 2026 treten iOS-Apps mit Apple Intelligence und dem App-Intents-Framework in eine Ära ein, in der die Nutzerintention wichtiger ist als die grafische Oberfläche. Apps ohne Intents werden in einem KI-zentrierten Betriebssystem unsichtbar. App Intents bilden das Fundament, das Siri, Spotlight, Widgets und dem Action Button erlaubt, mit App-Funktionen zu interagieren. > **Was dieser Artikel behandelt** > > Dieser Artikel zeigt die vollständige Erstellung von App Intents und Siri Shortcuts für iOS 18+, von den Grundlagen bis zur Integration mit Apple Intelligence und den App Intent Domains. ## Das App-Intents-Framework verstehen Das mit iOS 16 eingeführte App-Intents-Framework modernisiert die Erstellung von Intents in Swift und ersetzt das ältere SiriKit-Intents-Framework. Diese deklarative Architektur ermöglicht es, vom System auffindbare Aktionen zu erstellen: Spotlight, Kurzbefehle-App, Siri und Action Button. ```swift // TaskIntent.swift import AppIntents // Ein AppIntent repräsentiert eine Aktion, die Nutzer ausführen können struct CreateTaskIntent: AppIntent { // In Kurzbefehlen und Siri angezeigter Titel static var title: LocalizedStringResource = "Aufgabe erstellen" // Beschreibung für Barrierefreiheit und Vorschläge static var description = IntentDescription( "Erstellt eine neue Aufgabe in der App." ) // Parameter mit automatischer Validierung @Parameter(title: "Aufgabentitel") var taskTitle: String // Optionaler Parameter mit Standardwert @Parameter(title: "Priorität", default: .medium) var priority: TaskPriority // Aktionsausführung func perform() async throws -> some IntentResult & ReturnsValue { // Aufgabe über den Service erstellen let task = TaskService.shared.createTask( title: taskTitle, priority: priority ) // Erstellte Entity zur Verkettung zurückgeben return .result(value: TaskEntity(task: task)) } } ``` Der Intent deklariert seine Parameter über den Property Wrapper `@Parameter`, sodass Siri fehlende Werte abfragen kann. Die Methode `perform()` führt die Geschäftslogik aus und liefert ein typisiertes Ergebnis. ## App Entities für Daten definieren App Entities repräsentieren die "Substantive" der App: die Objekte, auf denen Intents operieren. Sie ermöglichen Siri das Verstehen und Manipulieren von App-Daten. ```swift // TaskEntity.swift import AppIntents // Internes Datenmodell struct Task: Identifiable, Codable { let id: UUID var title: String var priority: TaskPriority var isCompleted: Bool var dueDate: Date? } // Dem System exponierte Entity struct TaskEntity: AppEntity { // Erforderliche eindeutige Kennung var id: UUID // Anzeigbare Eigenschaften var title: String var priority: TaskPriority var isCompleted: Bool // Anzeigekonfiguration im System static var typeDisplayRepresentation: TypeDisplayRepresentation = "Aufgabe" // Visuelle Darstellung der Instanz var displayRepresentation: DisplayRepresentation { DisplayRepresentation( title: "\(title)", subtitle: "\(priority.rawValue)", image: .init(systemName: isCompleted ? "checkmark.circle.fill" : "circle") ) } // Standard-Query zur Suche von Entities static var defaultQuery = TaskEntityQuery() // Initializer aus dem internen Modell init(task: Task) { self.id = task.id self.title = task.title self.priority = task.priority self.isCompleted = task.isCompleted } } // Query zum Suchen und Filtern von Entities struct TaskEntityQuery: EntityQuery { // Suche nach IDs func entities(for identifiers: [UUID]) async throws -> [TaskEntity] { TaskService.shared.fetchTasks() .filter { identifiers.contains($0.id) } .map { TaskEntity(task: $0) } } // In der Oberfläche angezeigte Vorschläge func suggestedEntities() async throws -> [TaskEntity] { TaskService.shared.fetchTasks() .filter { !$0.isCompleted } .prefix(5) .map { TaskEntity(task: $0) } } } ``` Die `EntityQuery` definiert, wie das System Entities sucht und vorschlägt. Die Methoden `entities(for:)` und `suggestedEntities()` versorgen die Siri- und Kurzbefehle-Oberflächen. > **App Enums vs App Entities** > > Verwende `AppEnum` für Typen mit fester Wertemenge (Priorität, Status) und `AppEntity` für dynamische, vom Nutzer erstellte Typen (Aufgaben, Notizen, Kontakte). ## App Enums für feste Werte erstellen App Enums exponieren aufgezählte Typen an das System und ermöglichen Siri kontextbezogene Auswahlmöglichkeiten. ```swift // TaskPriority.swift import AppIntents // Dem System exponiertes Enum enum TaskPriority: String, AppEnum, Codable { case low case medium case high // Angezeigter Typname static var typeDisplayRepresentation: TypeDisplayRepresentation = "Priorität" // Darstellung jedes Falls static var caseDisplayRepresentations: [TaskPriority: DisplayRepresentation] = [ .low: DisplayRepresentation( title: "Niedrig", image: .init(systemName: "arrow.down.circle") ), .medium: DisplayRepresentation( title: "Mittel", image: .init(systemName: "minus.circle") ), .high: DisplayRepresentation( title: "Hoch", image: .init(systemName: "exclamationmark.circle") ) ] } // Enum für den Aufgabenstatus enum TaskStatus: String, AppEnum, Codable { case pending case inProgress case completed static var typeDisplayRepresentation: TypeDisplayRepresentation = "Status" static var caseDisplayRepresentations: [TaskStatus: DisplayRepresentation] = [ .pending: "Ausstehend", .inProgress: "In Bearbeitung", .completed: "Abgeschlossen" ] } ``` Visuelle Darstellungen (SF-Symbols-Icons) bereichern die Anzeige in Kurzbefehlen und Siri-Vorschlägen. ## AppShortcutsProvider implementieren Der `AppShortcutsProvider` exponiert App Shortcuts an das System und macht sie ohne Nutzerkonfiguration sofort verfügbar. Diese Shortcuts erscheinen in Spotlight, Siri und am Action Button. ```swift // ShortcutsProvider.swift import AppIntents // Provider, der alle App-Shortcuts deklariert struct TaskAppShortcutsProvider: AppShortcutsProvider { // Maximal 10 Shortcuts pro App @AppShortcutsBuilder static var appShortcuts: [AppShortcut] { // Shortcut zum Erstellen einer Aufgabe AppShortcut( intent: CreateTaskIntent(), phrases: [ // Der Platzhalter .applicationName ist PFLICHT "Aufgabe in \(.applicationName) erstellen", "Neue Aufgabe in \(.applicationName)", "Aufgabe zu \(.applicationName) hinzufügen" ], shortTitle: "Aufgabe erstellen", systemImageName: "plus.circle" ) // Shortcut zum Auflisten von Aufgaben AppShortcut( intent: ListTasksIntent(), phrases: [ "Meine Aufgaben in \(.applicationName) zeigen", "Aufgaben aus \(.applicationName) anzeigen", "Was sind meine Aufgaben \(.applicationName)" ], shortTitle: "Meine Aufgaben", systemImageName: "list.bullet" ) // Shortcut mit dynamischem Parameter AppShortcut( intent: CompleteTaskIntent(), phrases: [ "\(\.$taskName) in \(.applicationName) abschließen", "\(\.$taskName) als erledigt markieren mit \(.applicationName)" ], shortTitle: "Aufgabe abschließen", systemImageName: "checkmark.circle" ) } } ``` Sprachphrasen müssen den Platzhalter `\(.applicationName)` enthalten, damit Siri die Ziel-App identifiziert. Dynamische Parameter wie `\(\.$taskName)` ermöglichen kontextbezogene Befehle. > **10-Shortcuts-Limit** > > Eine App kann maximal 10 App Shortcuts deklarieren. Es empfiehlt sich, die häufigsten und nützlichsten Aktionen für Nutzer zu priorisieren. ## Intents mit komplexen Parametern Intents können komplexe Parameter inklusive Entities und Konfigurationsoptionen akzeptieren. ```swift // CompleteTaskIntent.swift import AppIntents struct CompleteTaskIntent: AppIntent { static var title: LocalizedStringResource = "Aufgabe abschließen" static var description = IntentDescription( "Markiert eine Aufgabe als abgeschlossen." ) // Entity-Parameter mit automatischer Suche @Parameter(title: "Aufgabe") var task: TaskEntity // Optionaler Parameter mit Datum @Parameter(title: "Abschlussdatum") var completionDate: Date? // Konfiguration des Siri-Dialogs static var parameterSummary: some ParameterSummary { Summary("\(\.$task) abschließen") { \.$completionDate } } func perform() async throws -> some IntentResult & ProvidesDialog { // Aufgabe aktualisieren TaskService.shared.completeTask( id: task.id, completionDate: completionDate ?? Date() ) // Sprachfeedback für Siri return .result( dialog: "Die Aufgabe \(task.title) wurde als abgeschlossen markiert." ) } } // Intent, der eine Liste von Entities zurückgibt struct ListTasksIntent: AppIntent { static var title: LocalizedStringResource = "Aufgaben auflisten" // Optionaler Filter @Parameter(title: "Status", default: nil) var statusFilter: TaskStatus? @Parameter(title: "Priorität", default: nil) var priorityFilter: TaskPriority? func perform() async throws -> some IntentResult & ReturnsValue<[TaskEntity]> { var tasks = TaskService.shared.fetchTasks() // Filter anwenden if let status = statusFilter { tasks = tasks.filter { switch status { case .completed: return $0.isCompleted case .pending, .inProgress: return !$0.isCompleted } } } if let priority = priorityFilter { tasks = tasks.filter { $0.priority == priority } } let entities = tasks.map { TaskEntity(task: $0) } return .result(value: entities) } } ``` Das `ParameterSummary` definiert, wie Siri den Intent während der Sprachausführung präsentiert, und liefert ein natürliches Feedback. ## Apple-Intelligence-Integration iOS 18 führt App Intent Domains ein, also Sammlungen von APIs für bestimmte Funktionen. Diese Domains ermöglichen Apple Intelligence ein präziseres Verstehen und Ausführen von Aktionen. ```swift // BookmarkDomainIntents.swift import AppIntents // Konformität mit der Bookmarks-Domain für Apple-Intelligence-Integration struct SaveBookmarkIntent: AppIntent { static var title: LocalizedStringResource = "Lesezeichen speichern" // Automatisch validierter URL-Parameter @Parameter(title: "URL") var url: URL @Parameter(title: "Titel", default: nil) var title: String? @Parameter(title: "Ordner", default: nil) var folder: BookmarkFolderEntity? // App bei Bedarf öffnen static var openAppWhenRun: Bool = false func perform() async throws -> some IntentResult & ProvidesDialog { let bookmark = BookmarkService.shared.save( url: url, title: title, folder: folder?.id ) return .result( dialog: "Lesezeichen gespeichert: \(bookmark.title)" ) } } // Intent mit Bewusstsein für Bildschirminhalt (iOS 18.4+) struct AnalyzeScreenContentIntent: AppIntent { static var title: LocalizedStringResource = "Inhalt analysieren" // Zugriff auf Bildschirmkontext via Apple Intelligence @Parameter(title: "Kontext") var screenContext: String? func perform() async throws -> some IntentResult & ProvidesDialog { guard let context = screenContext else { return .result(dialog: "Kein Inhalt zu analysieren.") } // Von Apple Intelligence extrahierten Inhalt verarbeiten let analysis = ContentAnalyzer.analyze(context) return .result(dialog: analysis.summary) } } ``` Vordefinierte Domains (Books, Camera, Spreadsheets) ermöglichen Siri präzise Antworten auf Anfragen dank auf diese Aufgaben trainierter Modelle. ## Siri-Aktionen mit Nutzerbestätigung Bei sensiblen Aktionen kann das System vor der Ausführung eine Bestätigung anfordern. ```swift // DeleteTaskIntent.swift import AppIntents struct DeleteTaskIntent: AppIntent { static var title: LocalizedStringResource = "Aufgabe löschen" @Parameter(title: "Aufgabe") var task: TaskEntity // Nutzerbestätigung erforderlich static var isDiscoverable: Bool = true func perform() async throws -> some IntentResult & ProvidesDialog { // Bestätigung per Dialog anfordern try await requestConfirmation( result: .result( dialog: "Soll \(task.title) wirklich gelöscht werden?" ) ) // Nach Bestätigung löschen TaskService.shared.deleteTask(id: task.id) return .result( dialog: "Die Aufgabe \(task.title) wurde gelöscht." ) } } // Intent mit mehreren Dialogschritten struct ScheduleTaskIntent: AppIntent { static var title: LocalizedStringResource = "Aufgabe planen" @Parameter(title: "Aufgabe") var task: TaskEntity @Parameter(title: "Datum") var scheduledDate: Date @Parameter(title: "Erinnerung", default: true) var setReminder: Bool static var parameterSummary: some ParameterSummary { When(\.$setReminder, .equalTo, true) { Summary("\(\.$task) am \(\.$scheduledDate) mit Erinnerung planen") } otherwise: { Summary("\(\.$task) am \(\.$scheduledDate) planen") } } func perform() async throws -> some IntentResult & ProvidesDialog { TaskService.shared.schedule( taskId: task.id, date: scheduledDate, reminder: setReminder ) let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium dateFormatter.timeStyle = .short let formattedDate = dateFormatter.string(from: scheduledDate) return .result( dialog: "Aufgabe geplant für \(formattedDate)." ) } } ``` Die Methode `requestConfirmation` pausiert die Ausführung bis zur Nutzerbestätigung und schützt vor versehentlichen Aktionen. ## Intents in interaktiven Widgets App Intents lassen sich nahtlos mit WidgetKit integrieren, um interaktive Widgets unter iOS 17+ zu erstellen. ```swift // TaskWidgetIntents.swift import AppIntents import WidgetKit // Für Widgets optimierter Intent (schnelle Ausführung) struct ToggleTaskFromWidgetIntent: AppIntent { static var title: LocalizedStringResource = "Aufgabe umschalten" @Parameter(title: "Aufgaben-ID") var taskID: String init() {} init(taskID: UUID) { self.taskID = taskID.uuidString } // Kein Dialog für Widgets func perform() async throws -> some IntentResult { guard let uuid = UUID(uuidString: taskID) else { return .result() } TaskService.shared.toggleCompletion(taskId: uuid) // Sofortige Widget-Aktualisierung WidgetCenter.shared.reloadTimelines(ofKind: "TaskWidget") return .result() } } // Widget-View mit interaktivem Button import SwiftUI struct TaskWidgetView: View { let task: Task var body: some View { Button(intent: ToggleTaskFromWidgetIntent(taskID: task.id)) { HStack { Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle") .foregroundStyle(task.isCompleted ? .green : .secondary) Text(task.title) .strikethrough(task.isCompleted) } .padding() } .buttonStyle(.plain) } } ``` Widgets nutzen die Syntax `Button(intent:)`, um die Interaktion direkt mit dem App Intent zu verbinden, ohne die App zu öffnen. ## Action-Button-Konfiguration Der Action Button auf dem iPhone 15 Pro und neueren Modellen kann App Shortcuts direkt auslösen. ```swift // ActionButtonIntent.swift import AppIntents // Für Action Button optimierter Intent struct QuickCaptureIntent: AppIntent { static var title: LocalizedStringResource = "Schnellaufnahme" static var description = IntentDescription( "Erstellt schnell eine Aufgabe mit Titel." ) // App für Eingabe öffnen static var openAppWhenRun: Bool = true func perform() async throws -> some IntentResult & OpensIntent { // Benachrichtigung zum Öffnen der Schnellaufnahme-Ansicht NotificationCenter.default.post( name: .quickCaptureTriggered, object: nil ) return .result(opensIntent: ShowQuickCaptureViewIntent()) } } // In AppShortcutsProvider für Action Button deklarieren extension TaskAppShortcutsProvider { @AppShortcutsBuilder static var appShortcuts: [AppShortcut] { // ... weitere Shortcuts AppShortcut( intent: QuickCaptureIntent(), phrases: [ "Schnellaufnahme \(.applicationName)", "Schnelle Notiz \(.applicationName)" ], shortTitle: "Aufnehmen", systemImageName: "bolt.circle" ) } } ``` Nutzer können den Action Button in Einstellungen > Action Button so konfigurieren, dass dieser Shortcut ausgelöst wird. > **Makros iOS 18+** > > iOS 18 führt die Makros `@DeferredProperty` und `@ComputedProperty` ein, um Boilerplate zu reduzieren. App Intents können auch in Swift Packages liegen, um plattformübergreifend wiederverwendet zu werden. ## Intents in Swift Packages App Intents lassen sich in Swift Packages definieren, um sie zwischen iOS, macOS und watchOS zu teilen. ```swift // Package.swift // swift-tools-version: 5.9 import PackageDescription let package = Package( name: "TaskIntents", platforms: [ .iOS(.v17), .macOS(.v14), .watchOS(.v10) ], products: [ .library(name: "TaskIntents", targets: ["TaskIntents"]) ], dependencies: [], targets: [ .target( name: "TaskIntents", dependencies: [] ) ] ) // Sources/TaskIntents/SharedIntents.swift import AppIntents // Plattformübergreifend geteilter Intent public struct SharedCreateTaskIntent: AppIntent { public static var title: LocalizedStringResource = "Aufgabe erstellen" @Parameter(title: "Titel") public var taskTitle: String public init() {} public func perform() async throws -> some IntentResult { // Geteilte Logik await TaskRepository.shared.create(title: taskTitle) return .result() } } // Plattformspezifische Erweiterung in der App #if os(iOS) extension SharedCreateTaskIntent { // iOS-spezifisches Verhalten static var openAppWhenRun: Bool = false } #endif ``` Diese Architektur hält den Code für die Intents an einer Stelle und passt das Verhalten je Plattform an. ## App Intents testen App Intents lassen sich wie jeder Swift-Code per Unit-Tests prüfen. ```swift // TaskIntentTests.swift import XCTest import AppIntents @testable import TaskApp final class TaskIntentTests: XCTestCase { override func setUp() { super.setUp() // Service für isolierte Tests zurücksetzen TaskService.shared.reset() } func testCreateTaskIntent() async throws { // Given var intent = CreateTaskIntent() intent.taskTitle = "Testaufgabe" intent.priority = .high // When let result = try await intent.perform() // Then let tasks = TaskService.shared.fetchTasks() XCTAssertEqual(tasks.count, 1) XCTAssertEqual(tasks.first?.title, "Testaufgabe") XCTAssertEqual(tasks.first?.priority, .high) } func testCompleteTaskIntent() async throws { // Given let task = TaskService.shared.createTask( title: "Aufgabe zum Abschließen", priority: .medium ) var intent = CompleteTaskIntent() intent.task = TaskEntity(task: task) // When _ = try await intent.perform() // Then let updatedTask = TaskService.shared.fetchTask(id: task.id) XCTAssertTrue(updatedTask?.isCompleted ?? false) } func testEntityQuery() async throws { // Given let task1 = TaskService.shared.createTask(title: "Aufgabe 1", priority: .low) let task2 = TaskService.shared.createTask(title: "Aufgabe 2", priority: .high) let query = TaskEntityQuery() // When let entities = try await query.entities(for: [task1.id, task2.id]) // Then XCTAssertEqual(entities.count, 2) } } ``` Die Tests prüfen das Intent-Verhalten unabhängig von der Systemoberfläche. ## Best Practices und Optimierungen Mehrere Muster sorgen für performante App Intents und eine optimale Nutzererfahrung. ```swift // BestPractices.swift import AppIntents // 1. Lokalisierte Phrasen struct LocalizedTaskIntent: AppIntent { static var title: LocalizedStringResource = "task.create.title" static var description = IntentDescription( "task.create.description", categoryName: "task.category" ) @Parameter(title: "task.parameter.title") var taskTitle: String func perform() async throws -> some IntentResult { // ... return .result() } } // 2. Saubere Fehlerbehandlung enum TaskIntentError: Error, CustomLocalizedStringResourceConvertible { case taskNotFound case invalidInput case serviceUnavailable var localizedStringResource: LocalizedStringResource { switch self { case .taskNotFound: return "Aufgabe nicht gefunden." case .invalidInput: return "Ungültige Daten." case .serviceUnavailable: return "Dienst vorübergehend nicht verfügbar." } } } struct RobustTaskIntent: AppIntent { static var title: LocalizedStringResource = "Robuster Intent" @Parameter(title: "ID") var taskId: String func perform() async throws -> some IntentResult & ProvidesDialog { guard let uuid = UUID(uuidString: taskId) else { throw TaskIntentError.invalidInput } guard let task = TaskService.shared.fetchTask(id: uuid) else { throw TaskIntentError.taskNotFound } return .result(dialog: "Aufgabe gefunden: \(task.title)") } } // 3. EntityQuery-Optimierung struct OptimizedTaskQuery: EntityStringQuery { // Optimierte Textsuche func entities(matching string: String) async throws -> [TaskEntity] { // Suche im Service mit Limit TaskService.shared.search(query: string, limit: 10) .map { TaskEntity(task: $0) } } // Vorschläge zur Performance limitieren func suggestedEntities() async throws -> [TaskEntity] { TaskService.shared.fetchRecentTasks(limit: 5) .map { TaskEntity(task: $0) } } } // 4. Focus Filter für Fokus-Modi struct TaskFocusFilter: SetFocusFilterIntent { static var title: LocalizedStringResource = "Aufgaben filtern" @Parameter(title: "Nur hohe Priorität anzeigen") var showHighPriorityOnly: Bool func perform() async throws -> some IntentResult { TaskService.shared.setFocusFilter(highPriorityOnly: showHighPriorityOnly) return .result() } } ``` Diese Muster sichern eine reibungslose Systemintegration bei optimaler Performance. ## Fazit App Intents und Siri Shortcuts verändern, wie Nutzer mit iOS-Apps interagieren. 2026 ist mit Apple Intelligence das Bereitstellen von Intents nicht mehr optional, sondern essenziell für eine moderne und intuitive Erfahrung. ### Checkliste App Intents iOS 18+ - ✅ AppIntents für die Hauptaktionen der App erstellen - ✅ AppEntities für manipulierbare Daten definieren - ✅ AppEnum für aufgezählte Typen verwenden - ✅ AppShortcutsProvider mit Sprachphrasen implementieren - ✅ Maximales Limit von 10 App Shortcuts einhalten - ✅ `\(.applicationName)` in allen Phrasen einbinden - ✅ ParameterSummary für Siri-Feedback konfigurieren - ✅ Apple-Intelligence-Domains nutzen, wenn passend - ✅ Intents mit Unit-Tests prüfen - ✅ Titel und Beschreibungen lokalisieren --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/de/blog/ios/app-intents-siri-shortcuts-advanced-ios-automation