0

I am seeing problems with my intent handler showing up in my logs that I don't understand.
Here's the relevant code

 func addAttendee(numberToAdd: Int) -> Int {
        self.numberOfAttendees += numberToAdd
        let intent = AddAttendeeIntent()
        intent.suggestedInvocationPhrase = "Add People"
        intent.people = NSNumber(value: numberToAdd)

        let interaction = INInteraction(intent: intent, response: nil)

        interaction.donate { (error) in
            if error != nil {
                if let error = error as NSError? {
                    self.logger.log("error occurred: \(error, privacy: .public)")
                }
            } else {
                self.logger.log("Add people Intent success")
            }
        }
        return (self.numberOfAttendees)
    }

The error I am seeing is as follows:

error occurred: Error Domain=IntentsErrorDomain Code=1901 "Cannot donate interaction with intent that has no valid shortcut types: <INInteraction: 0x6000002b0480> {
    intent = <INIntent: 0x6000014b0510> {
    };
    dateInterval = <_NSConcreteDateInterval: 0x600002670da0> (Start Date) 2023-03-05 01:30:08 +0000 + (Duration) 0.000000 seconds = (End Date) 2023-03-05 01:30:08 +0000;
    intentResponse = <null>;
    groupIdentifier = <null>;
    intentHandlingStatus = Unspecified;
    identifier = 8E92F53E-C532-4C3A-A58A-E30E2177A227;
    direction = Unspecified;
} for intent <AddAttendeeIntent: 0x600001490090> {
    people = 1;
}" UserInfo={NSLocalizedDescription=Cannot donate interaction with intent that has no valid shortcut types: <INInteraction: 0x6000002b0480> {
    intent = <INIntent: 0x6000014b0510> {
    };
    dateInterval = <_NSConcreteDateInterval: 0x600002670da0> (Start Date) 2023-03-05 01:30:08 +0000 + (Duration) 0.000000 seconds = (End Date) 2023-03-05 01:30:08 +0000;
    intentResponse = <null>;
    groupIdentifier = <null>;
    intentHandlingStatus = Unspecified;
    identifier = 8E92F53E-C532-4C3A-A58A-E30E2177A227;
    direction = Unspecified;
} for intent <AddAttendeeIntent: 0x600001490090> {
    people = 1;
}}

Looking at my Intent definitions I should be ok: Intent Definition Screen shot

And my intent handler is pretty simple too

    override func handler(for intent: INIntent) -> Any {
        // This is the default implementation.  If you want different objects to handle different intents,
        // you can override this and return the handler you want for that particular intent.
        logger.log("\(intent)")

        switch intent {
        case is AddAttendeeIntent:
            return AddAttendeeIntentHandler()
        case is RemoveAttendeeIntent:
            return RemoveAttendeeIntentHandler()
        case is StartMeetingIntent:
            return StartMeetingIntentHandler()
        case is EndMeetingIntent:
            return EndMeetingIntent()
        case is ResetMeetingIntent:
            return ResetMeetingIntent()
        case is QuorumReachedIntent:
            return QuorumReachedIntent()
        default:
            fatalError("Shortcut - No handler for this intent")
        }
    }

I am not sure what is meant by no valid shortcut type. If I change my Intent Handler to have a case of AddAttendee, it indicates that it does not exist. Any specific thing I am not seeing?

Michael Rowe
  • 870
  • 2
  • 11
  • 27

1 Answers1

1

I converted my code to App Shortcut following the Migrating to App Short cuts tech talk from apple and it now works. Here's the resultant code:

//
//  AddAttendee.swift
//  
//
//  Created by Michael Rowe on 3/4/23.
//

import Foundation
import AppIntents

@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct AddAttendee: AppIntent, CustomIntentMigratedAppIntent, PredictableIntent {
    static let intentClassName = "AddAttendeeIntent"

    static var title: LocalizedStringResource = "Add people to a meeting"
    static var description = IntentDescription("Add people to a meeting")

    @Parameter(title: "People", default: 1, requestValueDialog: "How many people do you want to add?")
    var people: Int

    static var parameterSummary: some ParameterSummary {
        Summary("Add \(\.$people) people to a meeting.")
    }

    static var predictionConfiguration: some IntentPredictionConfiguration {
        IntentPrediction(parameters: (\.$people)) { people in
            DisplayRepresentation(
                title: "Add \(people) people to a meeting.",
                subtitle: ""
            )
        }
    }

    func perform() async throws -> some IntentResult & ReturnsValue<Int> {
        // First attempt at converting to AppIntent
        if people < 0 {
            throw AddAttendeeError.negativeNumbersNotAllowed(people)
        } else if people > 1000 {
            throw AddAttendeeError.greaterThanMaximumValue(people)
        }

        try await requestConfirmation(result: .result(
            value: people,
            dialog: "Adding \(people) attendees, is that right?"
        ),
            confirmationActionName: .add,
            showPrompt: false)

        return .result(value: people, dialog: "Added \(people) attendees to meeting")
    }
}

enum AddAttendeeError: Error, CustomLocalizedStringResourceConvertible {
    case negativeNumbersNotAllowed(Int)
    case greaterThanMaximumValue(Int)

    var localizedStringResource: LocalizedStringResource {
        switch self {
        case .negativeNumbersNotAllowed(let people):
            return "You can't add \(people) attendees"
        case .greaterThanMaximumValue(let people):
            return "You can't add \(people) attendees"
        }
    }
}

fileprivate extension IntentDialog {
    static var peopleParameterPrompt: Self {
        "How many people do you want to add?"
    }
    static func responseSuccess(result: Int) -> Self {
        "\(result)"
    }
    static func responseFailure(error: String) -> Self {
        "\(error)"
    }
}
Michael Rowe
  • 870
  • 2
  • 11
  • 27