英文:
Siri enters loop of requesting parameter when running AppIntent
问题
我想要使用AppIntents
框架来添加快捷方式和Siri支持。使用快捷方式或从Spotlight中运行我的意图都没有问题,因为显示了基于触摸的UI来进行消歧义。然而,当我要求Siri执行此操作时,她陷入了一个循环,一直问我设置参数的问题。
我的AppIntent
实现如下:
struct StartSessionIntent: AppIntent {
static var title: LocalizedStringResource = "start_recording"
@Parameter(title: "activity", requestValueDialog: IntentDialog("which_activity"))
var activity: ActivityEntity
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
let activityToSelect: ActivityEntity = self.activity
guard let selectedActivity = Activity[activityToSelect.name] else {
return .result(dialog: "activity_not_found")
}
...
return .result(dialog: "recording_started \(selectedActivity.name.localized())")
}
}
ActivityEntity
的实现如下:
struct ActivityEntity: AppEntity {
static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "activity")
typealias DefaultQuery = MobilityActivityQuery
static var defaultQuery: MobilityActivityQuery = MobilityActivityQuery()
var id: String
var name: String
var icon: String
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "\(self.name.localized())", image: .init(systemName: self.icon))
}
}
struct MobilityActivityQuery: EntityQuery {
func entities(for identifiers: [String]) async throws -> [ActivityEntity] {
Activity.all()?.compactMap({ activity in
identifiers.contains(where: { $0 == activity.name }) ? ActivityEntity(id: activity.name, name: activity.name, icon: activity.icon) : nil
}) ?? []
}
func suggestedEntities() async throws -> [ActivityEntity] {
Activity.all()?.compactMap({ activity in
ActivityEntity(id: activity.name, name: activity.name, icon: activity.icon)
}) ?? []
}
}
有人知道可能是什么原因导致了这种情况,以及如何解决这个问题吗?提前感谢。
英文:
I want to add shortcut and Siri support using the AppIntents
framework. Running my intent using shortcuts or from spotlight works fine, as the touch based UI for the disambiguation is shown. However, when I ask Siri to perform this action, she gets into a loop of asking me the question to set the parameter.
My AppIntent
is implemented as following:
struct StartSessionIntent: AppIntent {
static var title: LocalizedStringResource = "start_recording"
@Parameter(title: "activity", requestValueDialog: IntentDialog("which_activity"))
var activity: ActivityEntity
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
let activityToSelect: ActivityEntity = self.activity
guard let selectedActivity = Activity[activityToSelect.name] else {
return .result(dialog: "activity_not_found")
}
...
return .result(dialog: "recording_started (selectedActivity.name.localized())")
}
}
The ActivityEntity
is implemented like this:
struct ActivityEntity: AppEntity {
static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "activity")
typealias DefaultQuery = MobilityActivityQuery
static var defaultQuery: MobilityActivityQuery = MobilityActivityQuery()
var id: String
var name: String
var icon: String
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "\(self.name.localized())", image: .init(systemName: self.icon))
}
}
struct MobilityActivityQuery: EntityQuery {
func entities(for identifiers: [String]) async throws -> [ActivityEntity] {
Activity.all()?.compactMap({ activity in
identifiers.contains(where: { $0 == activity.name }) ? ActivityEntity(id: activity.name, name: activity.name, icon: activity.icon) : nil
}) ?? []
}
func suggestedEntities() async throws -> [ActivityEntity] {
Activity.all()?.compactMap({ activity in
ActivityEntity(id: activity.name, name: activity.name, icon: activity.icon)
}) ?? []
}
}
Has anyone an idea what might be causing this and how I can fix this behavior? Thanks in advance.
答案1
得分: 1
- 第一个可能性是你没有为你的
@Parameter
设置default
属性。这个属性告诉 Siri 如果用户没有指定参数要使用什么值。如果你不设置这个属性,Siri 将始终要求用户设置参数。
要解决这个问题,你可以将 default
属性设置为参数的默认值。例如,如果你的参数是一个字符串,你可以将 default
属性设置为空字符串。
- 第二个可能性是你正在使用自定义的
IntentDialog
用于你的@Parameter
。如果你正在使用自定义的IntentDialog
,你需要确保对话框包含一种让用户取消请求的方法。如果用户取消请求,Siri 将无法设置参数,并会要求用户再次设置它。
要解决这个问题,你可以在你的 IntentDialog
中添加一个 cancel
按钮。这将允许用户在不设置参数的情况下取消请求。
以下是通过设置 default
属性来解决问题的示例:
struct StartSessionIntent: AppIntent {
static var title: LocalizedStringResource = "start_recording"
@Parameter(
title: "activity",
requestValueDialog: IntentDialog("which_activity"),
default: ""
)
var activity: String
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
let activityToSelect: ActivityEntity = Activity[activity] ?? ActivityEntity(id: "", name: "", icon: "")
guard let selectedActivity = Activity[activityToSelect.name] else {
return .result(dialog: "activity_not_found")
}
// ...
return .result(dialog: "recording_started \(selectedActivity.name.localized())")
}
}
以下是通过在 IntentDialog
中添加 cancel
按钮来解决问题的示例:
struct StartSessionIntent: AppIntent {
static var title: LocalizedStringResource = "start_recording"
@Parameter(
title: "activity",
requestValueDialog: IntentDialog("which_activity", buttons: [.cancel()])
)
var activity: String
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
let activityToSelect: ActivityEntity = Activity[activity] ?? ActivityEntity(id: "", name: "", icon: "")
guard let selectedActivity = Activity[activityToSelect.name] else {
return .result(dialog: "activity_not_found")
}
// ...
return .result(dialog: "recording_started \(selectedActivity.name.localized())")
}
}
希望这可以帮助你!
英文:
I can see two possible reasons why Siri might be asking you to set the parameter for your AppIntent multiple times.
- The first possibility is that you have not set the
default
property for your@Parameter
. This property tells Siri what value to use for the parameter if the user does not specify one. If you do not set this property, Siri will always ask the user to set the parameter.
To fix this, you can set the default
property to the default value for your parameter. For example, if your parameter is a string, you could set the default
property to an empty string.
- The second possibility is that you are using a custom
IntentDialog
for your@Parameter
. If you are using a customIntentDialog
, you need to make sure that the dialog includes a way for the user to cancel the request. If the user cancels the request, Siri will not be able to set the parameter and will ask the user to set it again.
To fix this, you can add a cancel
button to your IntentDialog
. This will allow the user to cancel the request without setting the parameter.
Here is an example of how you could fix the problem by setting the default
property:
struct StartSessionIntent: AppIntent {
static var title: LocalizedStringResource = "start_recording"
@Parameter(
title: "activity",
requestValueDialog: IntentDialog("which_activity"),
default: ""
)
var activity: String
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
let activityToSelect: ActivityEntity = Activity[activity] ?? ActivityEntity(id: "", name: "", icon: "")
guard let selectedActivity = Activity[activityToSelect.name] else {
return .result(dialog: "activity_not_found")
}
...
return .result(dialog: "recording_started \(selectedActivity.name.localized())")
}
}
Here is an example of how you could fix the problem by adding a `cancel` button to your `IntentDialog`:
struct StartSessionIntent: AppIntent {
static var title: LocalizedStringResource = "start_recording"
@Parameter(
title: "activity",
requestValueDialog: IntentDialog("which_activity", buttons: [.cancel()])
)
var activity: String
@MainActor
func perform() async throws -> some IntentResult & ProvidesDialog {
let activityToSelect: ActivityEntity = Activity[activity] ?? ActivityEntity(id: "", name: "", icon: "")
guard let selectedActivity = Activity[activityToSelect.name] else {
return .result(dialog: "activity_not_found")
}
...
return .result(dialog: "recording_started \(selectedActivity.name.localized())")
}
}
I hope this helps!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论