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:
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?
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)"
}
}