Empower users to interact with your app through voice, Shortcuts, and intelligent suggestions.
Quick Start
Add Intents Extension
- File → New → Target → Intents Extension
- Enable "Include UI Extension" if customizing Siri interface
- Enable Siri capability in main app target (Signing & Capabilities)
Minimal Intent Handler
import Intents
class IntentHandler: INExtension { override func handler(for intent: INIntent) -> Any { switch intent { case is OrderSoupIntent: return OrderSoupIntentHandler() default: return self } } }
class OrderSoupIntentHandler: NSObject, OrderSoupIntentHandling { // 1. Resolve parameters func resolveSoup(for intent: OrderSoupIntent) async -> SoupResolutionResult { guard let soup = intent.soup else { return .needsValue() } return .success(with: soup) }
// 2. Confirm intent
func confirm(intent: OrderSoupIntent) async -> OrderSoupIntentResponse {
return OrderSoupIntentResponse(code: .ready, userActivity: nil)
}
// 3. Handle intent
func handle(intent: OrderSoupIntent) async -> OrderSoupIntentResponse {
// Fulfill the request
return OrderSoupIntentResponse.success(message: "Your order is confirmed!")
}
}
## Intent Handling Flow
┌─────────────────────────────────────────────────────────────┐ │ User speaks to Siri │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. RESOLVE - Validate each parameter │ │ • Return .success(with:) if valid │ │ • Return .needsValue() if missing │ │ • Return .disambiguation(with:) for choices │ │ • Return .unsupported() if invalid │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 2. CONFIRM - Final validation before execution │ │ • Verify services are ready │ │ • Return .ready or appropriate failure code │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 3. HANDLE - Fulfill the intent │ │ • Execute the action │ │ • Return success/failure response │ └─────────────────────────────────────────────────────────────┘
## System Intent Domains
| Domain | Use Cases | Key Intents |
|--------|-----------|-------------|
| **Messaging** | Send/search messages | `INSendMessageIntent`, `INSearchForMessagesIntent` |
| **Calling** | VoIP calls | `INStartCallIntent`, `INSearchCallHistoryIntent` |
| **Payments** | Money transfers | `INSendPaymentIntent`, `INRequestPaymentIntent` |
| **Ride Booking** | Request rides | `INRequestRideIntent`, `INGetRideStatusIntent` |
| **Workouts** | Start/end workouts | `INStartWorkoutIntent`, `INEndWorkoutIntent` |
| **Media** | Play audio/video | `INPlayMediaIntent`, `INAddMediaIntent` |
| **Photos** | Search photos | `INSearchForPhotosIntent` |
| **Lists & Notes** | Create notes/tasks | `INCreateNoteIntent`, `INAddTasksIntent` |
| **Car Commands** | Vehicle controls | `INSetCarLockStatusIntent`, `INActivateCarSignalIntent` |
| **Reservations** | Restaurant bookings | `INGetReservationDetailsIntent` |
## Custom Intents
### Define in Intent Definition File
1. Create `Intents.intentdefinition` file
2. Add new intent with VerbNoun naming (e.g., `OrderSoup`)
3. Set category matching purpose
4. Define parameters with types
### Parameter Types
- **System**: String, Integer, Boolean, Date, Person, Location, Currency
- **Custom**: Define your own types as enums or objects
## Reference Documentation
- **[Intent Handling](references/intent-handling.md)**: Resolution, confirmation, handling patterns
- **[Shortcuts](references/shortcuts.md)**: Donating, suggesting, and managing shortcuts
- **[Custom Intents](references/custom-intents.md)**: Intent definition file, parameters, responses
- **[IntentsUI](references/intents-ui.md)**: Custom Siri interface views
- **[Vocabulary](references/vocabulary.md)**: Custom terminology and phrases
- **[App Intents Migration](references/app-intents.md)**: Modern App Intents framework
## Key Configuration
### Info.plist (Intents Extension)
```xml
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>OrderSoupIntent</string>
</array>
<key>IntentsRestrictedWhileLocked</key>
<array>
<string>INSendPaymentIntent</string>
</array>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.intents-service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).IntentHandler</string>
</dict>
Request Siri Authorization
import Intents
INPreferences.requestSiriAuthorization { status in
switch status {
case .authorized: print("Siri authorized")
case .denied: print("Siri denied")
case .notDetermined: print("Not determined")
case .restricted: print("Restricted")
@unknown default: break
}
}
Common Patterns
Donate Shortcut After User Action
import Intents
func donateOrderShortcut(order: Order) {
let intent = OrderSoupIntent()
intent.soup = order.soup
intent.quantity = order.quantity
let interaction = INInteraction(intent: intent, response: nil)
interaction.identifier = order.id.uuidString
interaction.donate { error in
if let error = error {
print("Donation failed: \(error)")
}
}
}
Delete Donated Shortcuts
// Delete specific
INInteraction.delete(with: [orderID.uuidString]) { error in }
// Delete all from app
INInteraction.deleteAll { error in }
Handle Intent in App (when launched)
// SwiftUI
.onContinueUserActivity(NSStringFromClass(OrderSoupIntent.self)) { activity in
if let intent = activity.interaction?.intent as? OrderSoupIntent {
handleOrderIntent(intent)
}
}
// UIKit SceneDelegate
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let intent = userActivity.interaction?.intent as? OrderSoupIntent {
handleOrderIntent(intent)
}
}
Key Constraints
- Background execution: Extensions run briefly; launch app for long tasks
- Shared data: Use App Groups for data between app and extension
- No UI in extension: Use IntentsUI extension for custom views
- Testing: Wait after install for Siri to recognize new intents
- Localization: Provide localized
AppIntentVocabulary.plist