Інтеграція Siri для голосового управління iOS-програмою
Siri Shortcuts дозволяють користувачам запускати функції вашої програми голосом без ручного відкриття. Користувач говорить «Гей Siri, додай молоко в список» — і програма обробляє команду у фоні, без показу інтерфейсу. Це не UIApplicationShortcutItem для 3D Touch — це повноцінна NLP-інтеграція через SiriKit.
Два підходи: Intents vs NSUserActivity
NSUserActivity + INVoiceShortcut — найпростіший шлях. Помічаємо активність як «підтримує Siri» і користувач сам назначає їй фразу в налаштуваннях Shortcuts:
let activity = NSUserActivity(activityType: "com.yourapp.openDashboard")
activity.title = "Відкрити дашборд"
activity.isEligibleForSearch = true
activity.isEligibleForPrediction = true // важливо для Siri Suggestions
activity.suggestedInvocationPhrase = "Відкрий мій дашборд"
view.userActivity = activity
activity.becomeCurrent()
Коли користувач вимовляє назначену фразу — програма відкривається і отримує activity через application(_:continue:restorationHandler:). Мінус: не працює у фоні, потребує відкриття програми.
INIntent + INExtension — потужніше. Команда обробляється у фоні через App Extension, не потребуючи відкриття основної програми. Саме так працює «Увімкни світло» або «Замовте таксі».
Реалізація через кастомний Intent
Xcode → File → New → Target → Intents Extension. Створюємо файл .intentdefinition з описом параметрів:
Intent: AddItemIntent
Parameters:
- itemName: String (обов'язковий)
- listName: String (опціональний)
Response:
- success: "Додано \(itemName) до \(listName)"
- failure: "Не удалось додати"
Handler в extension:
class AddItemIntentHandler: NSObject, AddItemIntentHandling {
func handle(intent: AddItemIntent,
completion: @escaping (AddItemIntentResponse) -> Void) {
guard let itemName = intent.itemName else {
completion(AddItemIntentResponse(code: .failure, userActivity: nil))
return
}
// Звертаємось до shared App Group container
let store = ListStore(appGroup: "group.com.yourapp")
store.addItem(itemName, to: intent.listName ?? "Основний список")
let response = AddItemIntentResponse(code: .success, userActivity: nil)
response.itemName = itemName
completion(response)
}
func resolveItemName(for intent: AddItemIntent,
with completion: @escaping (INStringResolutionResult) -> Void) {
if let name = intent.itemName, !name.isEmpty {
completion(.success(with: name))
} else {
completion(.needsValue())
}
}
}
App Groups — обов'язкові для доступу Extension до даних основної програми. Extension та основний таргет додаються в одну App Group (group.com.yourapp), SharedFileList/UserDefaults ініціалізуються через цей ідентифікатор.
Siri Vocabulary: підвищуємо точність розпізнавання
Для предметно-специфичних слів (імена, терміни) — INVocabulary.shared().setVocabularyStrings(names, of: .contactGroupName). Для користувацького контенту (назви плейлистів, завдань) — файл AppIntentVocabulary.plist в основному бандлі з глобальними термінами.
Без цього Siri може транскрибувати «додай у Inbox» як «додай у inbox» (строчні) або «додай у index» — особливо з нестандартними іменами.
Тестування
Симулятор підтримує тестування Intents через Xcode: запускаємо схему Intents Extension з параметрами з .intentdefinition. Але голосове розпізнавання — тільки на реальному пристрої. Перший запуск Intent-запиту займає час: Siri навчає свою модель під користувача.
Інструмент відладки — os_log з subsystem com.apple.siri, плюс стандартний Xcode Console при запущеному extension.
Процес роботи
Аналіз функціоналу програми: що має смисл вимовляти голосом, які параметри.
Вибір підходу: NSUserActivity (прості навігаційні shortcuts) або кастомні Intents (дії у фоні).
Розробка: .intentdefinition, Intent Handler, App Groups для shared state.
Реєстрація Intent в Info.plist основної програми та extension.
Тестування на реальному пристрої, Siri Vocabulary для специфичних термінів.
Ориентири по срокам
Прості shortcuts через NSUserActivity — 1 день. Кастомний INIntent з App Extension та App Groups — 3–5 днів з урахуванням тестування на пристрої та налаштування Vocabulary.







