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.

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.
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.
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<TaskEntity> {
// 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.
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.
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.
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.
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.
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.
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.
Bereit für deine iOS-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
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.
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.
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.
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.
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.
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-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
}
#endifDiese 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.
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.
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
Fang an zu üben!
Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.
Tags
Teilen
Verwandte Artikel

WidgetKit iOS 17+: Interaktive Widgets mit App Intents
Vollständige Anleitung zur Erstellung interaktiver iOS-Widgets mit WidgetKit und App Intents. Buttons, Toggles, Animationen und Best Practices für iOS 17+ in 2026.

Combine vs async/await in Swift: Progressive Migrationsmuster
Vollständiger Leitfaden zur Migration von Combine zu async/await in Swift: progressive Strategien, Bridging-Muster und Paradigmen-Koexistenz in iOS-Codebasen.

iOS-Accessibility-Interviewfragen 2026: VoiceOver und Dynamic Type
Vorbereitung auf iOS-Interviews mit zentralen Accessibility-Fragen: VoiceOver, Dynamic Type, semantische Traits und Audits.