SiriKit enables your app to work with Siri using voice commands. Learn to implement intents and custom responses.
SiriKit Setup
Add Siri Capability
- 1Go to Project Settings > Signing & Capabilities
- 2Add "Siri" capability
- 3Define intents in Intent Definition file
Intent Extension
Create Intent Extension
swift
import Intents
class SendMessageIntentHandler: NSObject, SendMessageIntentHandling {
func handle(intent: SendMessageIntent, completion: @escaping (SendMessageIntentResponse) -> Void) {
guard let recipient = intent.recipient,
let message = intent.message else {
completion(MessageSendIntentResponse(code: .failure, userActivity: nil))
return
}
// Send message logic
sendMessage(to: recipient, message: message) { success in
if success {
let response = SendMessageIntentResponse.success(userActivity: nil)
completion(response)
} else {
completion(MessageSendIntentResponse.failure(failureError: nil, userActivity: nil))
}
}
}
func resolveRecipient(for intent: SendMessageIntent, with completion: @escaping (INSpeakableStringResolutionResult) -> Void) {
if let recipient = intent.recipient {
completion(.success(with: recipient))
} else {
completion(.disambiguation(with: [], needsValue: nil))
}
}
func resolveMessage(for intent: SendMessageIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
if let message = intent.message {
completion(.success(with: message))
} else {
completion(.needsValue())
}
}
private func sendMessage(to recipient: String, message: String, completion: @escaping (Bool) -> Void) {
// Message sending logic
completion(true)
}
}Custom Intents
Define Intent
swift
// Intent Definition File
// Intent Definition: Start Workout
import Intents
@objc(StartWorkoutIntent)
public class StartWorkoutIntent: NSObject, INIntent {
@objc public var workoutType: INSpeakableString?
@objc public var duration: NSNumber?
@NSManaged public var suggestedInvocationPhrase: String?
convenience init(workoutType: String, duration: Int) {
self.init()
self.workoutType = INSpeakableString(spokenPhrase: workoutType)
self.duration = NSNumber(value: duration)
}
}
// Intent Handler
class StartWorkoutIntentHandler: NSObject, StartWorkoutIntentHandling {
func handle(intent: StartWorkoutIntent, completion: @escaping (StartWorkoutIntentResponse) -> Void) {
guard let workoutType = intent.workoutType?.spokenPhrase,
let duration = intent.duration?.intValue else {
completion(StartWorkoutIntentResponse(code: .failure, userActivity: nil))
return
}
// Start workout
startWorkout(type: workoutType, duration: duration) { success in
if success {
let response = StartWorkoutIntentResponse.success(userActivity: nil)
completion(response)
} else {
completion(StartWorkoutIntentResponse.failure(failureError: nil, userActivity: nil))
}
}
}
func resolveWorkoutType(for intent: StartWorkoutIntent, with completion: @escaping (INSpeakableStringResolutionResult) -> Void) {
if let workoutType = intent.workoutType {
completion(.success(with: workoutType))
} else {
completion(.disambiguation(with: ["Running", "Cycling", "Swimming"], needsValue: nil))
}
}
func resolveDuration(for intent: StartWorkoutIntent, with completion: @escaping (INIntegerResolutionResult) -> Void) {
if let duration = intent.duration {
completion(.success(with: duration))
} else {
completion(.needsValue())
}
}
private func startWorkout(type: String, duration: Int, completion: @escaping (Bool) -> Void) {
// Workout start logic
completion(true)
}
}Intent UI
Custom Intent UI
swift
class WorkoutIntentViewController: UIViewController, INUIHostedViewControllerControlling {
func configureView(for intent: StartWorkoutIntent, with context: INIntentHostViewContext, completion: @escaping (CGSize, INUIHostedViewControllerDesiredMetrics) -> Void) {
let desiredSize = CGSize(width: 320, height: 100)
completion(desiredSize, .full)
}
func configureViewForInteraction(with intent: StartWorkoutIntent, context: INIntentHostViewContext, interaction: INUIHostedViewInteraction) {
// Configure interaction
}
}Siri Shortcuts
Donate Intent
swift
import Intents
class ShortcutDonationManager {
func donateWorkoutShortcut(workoutType: String, duration: Int) {
let intent = StartWorkoutIntent(workoutType: workoutType, duration: duration)
let interaction = INInteraction(intent: intent, response: nil)
interaction.donate { error in
if let error = error {
print("Error donating shortcut: \(error)")
} else {
print("Shortcut donated successfully")
}
}
}
func donateSendMessageShortcut(to recipient: String) {
let intent = SendMessageIntent()
intent.recipient = INPerson(handle: recipient)
intent.message = "Test message"
let interaction = INInteraction(intent: intent, response: nil)
interaction.donate { error in
if let error = error {
print("Error donating shortcut: \(error)")
}
}
}
}INAppAccount
Account Integration
swift
class AppAccountManager {
func saveAccount(username: String) {
let account = INAppAccount(
accountName: INSpeakableString(spokenPhrase: username)
)
let accountInteraction = INInteraction(account: account)
accountInteraction.donate { error in
if let error = error {
print("Error donating account: \(error)")
}
}
}
func removeAccount(username: String) {
// Remove account logic
}
}Siri Suggestions
Enable Suggestions
swift
class SiriSuggestionsManager {
func donateSearchResult(query: String) {
let intent = INSearchForItemsIntent()
intent.searchQuery = query
let response = INSearchForItemsIntentResponse(
searchedItems: [],
searchResults: [],
userActivity: NSUserActivity(activityType: "com.yourapp.search")
)
let interaction = INInteraction(intent: intent, response: response)
interaction.donate { error in
if let error = error {
print("Error donating suggestion: \(error)")
}
}
}
}Voice Shortcuts
Custom Phrases
swift
extension ShortcutDonationManager {
func donateCustomPhrase(phrase: String, intent: INIntent) {
let interaction = INInteraction(intent: intent, response: nil)
interaction.donation {
donationError in
if let donationError = donationError {
print("Error donating phrase: \(donationError)")
} else {
print("Phrase donated: \(phrase)")
}
}
}
}Best Practices
- 1Phrases: Use natural phrases
- 2Testing: Test voice commands thoroughly
- 3Responses: Provide clear responses
- 4Fallback: Handle failures gracefully
- 5Consistency: Keep responses consistent
- 6Context: Maintain context across interactions
- 7Performance: Optimize intent handling
- 8User Experience: Focus on user experience
SiriKit enables powerful voice control in your apps!