Simple App mit Siri Support (Daten in Core Data)

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Simple App mit Siri Support (Daten in Core Data)

    Hallo Community !

    ich bin neu hier in diesem Forum, da ich erst seit kurzem mit dem Thema "Meine erste App" angefangen habe.
    Hoffe auch eure Unterstützung :)

    Installiert habe ich auf meinem MacBook Air Xcode 12 und arbeite mit swift.
    Bislang habe ich eine App, die relativ simple gestrickt ist:

    Ein Textfiled, wo der user eine Eingabe tätigt "15,00"
    Ein Button "Save" der diese Eingabe in Core Data speichert
    Ein Label "0,00" -> Hier wird die Summe aus Core Data angezeigt

    Funktioniert tadellos und bin sehr stolz darauf ! :)
    Für euch sicherlich eine Kleinigkeit, für mich ein Wunder ! :D


    Nun würde ich gerne ein Schritt weitergehen.
    Mein Wunsche wäre, dass ich via Siri (außerhalb der App) einen Betrag in Core Data speichern kann.

    "Hey Siri, speichere den Wert 15,00 (oder so ähnlich)

    Habe mir einige Tutorials angesehen und habe verstanden, dass ich SiriKit benötige und mit "Intents" arbeiten muss.
    Aber so wirklich schlau bin ich daraus noch nicht geworden, da diese Tutorials immer mit der Siri Shortcut App zusammen arbeiten (ist diese dafür zwingend erforderlich)

    Hoffe Ihr könnt mir auf die Sprünge helfen, eventuell sogar ein Beispiel zeigen?
    Vielen lieben Dank ! :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von flowerbee ()

  • Du programmierst eine "Siri Intent"-Extension, die zur gleichen App Group wie die Haupt-App gehört und somit Zugriff auf die Daten hat. In dieser Extension hast Du Handler für die verschiedenen Intents, die in der info.plist definiert werden. Diese Handler führen die Aktionen z. B. in Core Data aus und geben einen Response.

    Nun musst Du in der Haupt-App diese Intents noch einer INInteraction zuordnen und diese per "donateInteraction..." Siri bekanntgeben. Nun hast Du in Siri entsprechende Aktionen verfügbar - z. B. in der Suche oder als Vorschlag. Diese kannst Du dann in der Shortcuts-App zu einem Workflow hinzufügen und mit einem (zu sprechenden) Kommando versehen.

    Soweit ist kein SiriKit erforderlich, das brauchst Du nur, wenn Du den o. g. Weg in Deiner App mit einem "Add to Siri"-Button unterstützen willst. Zwingend erforderlich ist das nicht.

    Mattes

    P.S.: Seit iOS 14 ist es mir nicht mehr gelungen, die o. g. Responses auch von Siri gesprochen zu bekommen (Forums-Post)
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • sorry, hatte etwas stress und bin jetzt erst dazu gekommen.

    habe das hier versucht, leider "erkennt" sir meinen Befehl nicht:

    ViewController


    Quellcode

    1. import UIKit
    2. import Intents
    3. import IntentsUI
    4. class ViewController: UIViewController {
    5. override func viewDidLoad() {
    6. super.viewDidLoad()
    7. // Do any additional setup after loading the view.
    8. addSiriButton(to: self.view)
    9. }
    10. func addSiriButton(to view: UIView) {
    11. if #available(iOS 12.0, *) {
    12. let button = INUIAddVoiceShortcutButton(style: .whiteOutline)
    13. button.shortcut = INShortcut(intent: intent )
    14. button.delegate = self
    15. button.translatesAutoresizingMaskIntoConstraints = false
    16. view.addSubview(button)
    17. view.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
    18. view.centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true
    19. }
    20. }
    21. }
    22. extension ViewController {
    23. @available(iOS 12.0, *)
    24. public var intent: DoSomethingIntent {
    25. let testIntent = DoSomethingIntent()
    26. testIntent.suggestedInvocationPhrase = "my test command"
    27. return testIntent
    28. }
    29. }
    30. extension ViewController: INUIAddVoiceShortcutButtonDelegate {
    31. @available(iOS 12.0, *)
    32. func present(_ addVoiceShortcutViewController: INUIAddVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {
    33. addVoiceShortcutViewController.delegate = self
    34. addVoiceShortcutViewController.modalPresentationStyle = .formSheet
    35. present(addVoiceShortcutViewController, animated: true, completion: nil)
    36. }
    37. @available(iOS 12.0, *)
    38. func present(_ editVoiceShortcutViewController: INUIEditVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {
    39. editVoiceShortcutViewController.delegate = self
    40. editVoiceShortcutViewController.modalPresentationStyle = .formSheet
    41. present(editVoiceShortcutViewController, animated: true, completion: nil)
    42. }
    43. }
    44. extension ViewController: INUIAddVoiceShortcutViewControllerDelegate {
    45. @available(iOS 12.0, *)
    46. func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
    47. controller.dismiss(animated: true, completion: nil)
    48. }
    49. @available(iOS 12.0, *)
    50. func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
    51. controller.dismiss(animated: true, completion: nil)
    52. }
    53. }
    54. extension ViewController: INUIEditVoiceShortcutViewControllerDelegate {
    55. @available(iOS 12.0, *)
    56. func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didUpdate voiceShortcut: INVoiceShortcut?, error: Error?) {
    57. controller.dismiss(animated: true, completion: nil)
    58. }
    59. @available(iOS 12.0, *)
    60. func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID) {
    61. controller.dismiss(animated: true, completion: nil)
    62. }
    63. @available(iOS 12.0, *)
    64. func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) {
    65. controller.dismiss(animated: true, completion: nil)
    66. }
    67. }
    Alles anzeigen





    IntentHandler


    Quellcode

    1. import Intents
    2. class IntentHandler: INExtension {
    3. override func handler(for intent: INIntent) -> Any {
    4. print("\(intent)")
    5. switch intent {
    6. case is DoSomethingIntent:
    7. return ShortcutIntentHandler()
    8. default:
    9. fatalError("No handler for this intent")
    10. }
    11. }
    12. }
    Alles anzeigen

    ShortcutIntentHandler


    Quellcode

    1. import Foundation
    2. import Intents
    3. import IntentsUI
    4. class ShortcutIntentHandler : NSObject, DoSomethingIntentHandling {
    5. func handle(intent: DoSomethingIntent, completion: @escaping (DoSomethingIntentResponse) -> Void) {
    6. print("handle")
    7. }
    8. func resolveAmount(for intent: DoSomethingIntent, with completion: @escaping (DoSomethingAmountResolutionResult) -> Void) {
    9. print("resolveAmount")
    10. }
    11. }
    Alles anzeigen



    Ergebnis
    Bildschirmfoto 2020-11-23 um 08.49.35.png Bildschirmfoto 2020-11-23 um 10.47.41.png
  • Bin ein Schritt weiter.

    Custom Intent
    eYdKg.png

    ViewController (mit add-Siri-Button)

    Quellcode

    1. class ViewController: UIViewController {
    2. override func viewDidLoad() {
    3. super.viewDidLoad()
    4. let button = INUIAddVoiceShortcutButton(style: .whiteOutline)
    5. button.shortcut = INShortcut(intent: intent )
    6. button.delegate = self
    7. button.translatesAutoresizingMaskIntoConstraints = false
    8. view.addSubview(button)
    9. view.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
    10. view.centerYAnchor.constraint(equalTo: button.bottomAnchor).isActive = true
    11. }
    12. }
    13. extension ViewController {
    14. public var intent: DoSomethingIntent {
    15. let intent = DoSomethingIntent()
    16. intent.suggestedInvocationPhrase = "Start my command"
    17. intent.betrag = "betrag"
    18. let interaction = INInteraction(intent: intent, response: nil)
    19. interaction.donate { (error) in
    20. if error != nil {
    21. if let error = error as NSError? {
    22. print("Interaction donation failed: \(error.description)")
    23. } else {
    24. print("Successfully donated interaction")
    25. }
    26. }
    27. }
    28. return intent
    29. }
    30. }
    31. extension ViewController: INUIAddVoiceShortcutButtonDelegate {
    32. func present(_ addVoiceShortcutViewController: INUIAddVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {
    33. addVoiceShortcutViewController.delegate = self
    34. addVoiceShortcutViewController.modalPresentationStyle = .popover
    35. present(addVoiceShortcutViewController, animated: true, completion: nil)
    36. }
    37. func present(_ editVoiceShortcutViewController: INUIEditVoiceShortcutViewController, for addVoiceShortcutButton:
    38. INUIAddVoiceShortcutButton) {
    39. editVoiceShortcutViewController.delegate = self
    40. editVoiceShortcutViewController.modalPresentationStyle = .popover
    41. present(editVoiceShortcutViewController, animated: true, completion: nil)
    42. }
    43. }
    44. extension ViewController: INUIAddVoiceShortcutViewControllerDelegate {
    45. func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
    46. controller.dismiss(animated: true, completion: nil)
    47. }
    48. func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
    49. controller.dismiss(animated: true, completion: nil)
    50. }
    51. }
    52. extension ViewController: INUIEditVoiceShortcutViewControllerDelegate {
    53. func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didUpdate voiceShortcut: INVoiceShortcut?, error: Error?) {
    54. controller.dismiss(animated: true, completion: nil)
    55. }
    56. func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID) {
    57. controller.dismiss(animated: true, completion: nil)
    58. }
    59. func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) {
    60. controller.dismiss(animated: true, completion: nil)
    61. }
    62. }
    Alles anzeigen


    IntentHandler Class

    Quellcode

    1. import Intents
    2. class IntentHandler: INExtension {
    3. override func handler(for intent: INIntent) -> Any {
    4. guard intent is DoSomethingIntent else {
    5. fatalError("Unknown Intent: \(intent)")
    6. }
    7. return DoSomethingIntentHandler()
    8. }
    9. }

    intentHandlingClass


    Quellcode

    1. import Foundation
    2. import Intents
    3. class DoSomethingIntentHandler: NSObject, DoSomethingIntentHandling {
    4. func confirm(intent: DoSomethingIntent, completion: @escaping (DoSomethingIntentResponse) -> Void) {
    5. print("Confirm")
    6. }
    7. func handle(intent: DoSomethingIntent, completion: @escaping (DoSomethingIntentResponse) -> Void) {
    8. print("handle")
    9. }
    10. func resolveBetrag(for intent: DoSomethingIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
    11. print("resolveBetrag")
    12. }
    13. }
    Alles anzeigen

    Mein jetziger Stand:

    • Ich kann meinen Siri Befehl via add-Siri-Button hinzufügen
    • Der Sprachbefehl wird erkannt, Siri öffnet daraufhin die App
    • Allerdings werde ich von Siri nicht nach dem Parameter "betrag" gefragt
    • Nachdem die App geöffnet wurde, passiert auch nichts mehr. Keine "Print" Ausgabe o.ä.
    Wo ist mein Fehler?
  • Sorry, ich habe nur mit einer Siri-Intent-Extension meiner App gearbeitet, die Haupt-Applikation wird bei mir nicht benötigt / gestartet. Für mich klingt es aber nach einer fehlenden Methode im AppDelegate, um die übergebene UserAction zu händeln.

    Die Text-Ausgabe des Intents wird bei mir in dessen Definition mit einer Variablen hinterlegt, die o. g. Extension dann im IntentHandler füllt.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.