swift Siri在运行AppIntent时进入请求参数的循环

eqqqjvef  于 2023-06-21  发布在  Swift
关注(0)|答案(1)|浏览(202)

我想使用AppIntents框架添加快捷方式和Siri支持。使用快捷方式或从spotlight运行我的intent工作正常,因为显示了用于消除歧义的基于触摸的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)
        }) ?? []
    }
}

有没有人知道是什么原因导致了这种情况,以及我如何修复这种行为?先谢谢你了。

amrnrhlw

amrnrhlw1#

我可以看到Siri多次要求您为AppIntent设置参数的两个可能原因。
1.第一种可能性是您没有为@Parameter设置default属性。此属性告诉Siri在用户未指定参数值的情况下要使用的参数值。如果您未设置此属性,Siri将始终要求用户设置参数。
要解决此问题,可以将default属性设置为参数的默认值。例如,如果参数是字符串,则可以将default属性设置为空字符串。
1.第二种可能性是您正在为您的@Parameter使用自定义的IntentDialog。如果您使用的是自定义IntentDialog,则需要确保对话框包含用户取消请求的方法。如果用户取消请求,Siri将无法设置参数,并会要求用户重新设置。
要解决这个问题,您可以将cancel按钮添加到IntentDialog。这将允许用户在不设置参数的情况下取消请求。
下面是一个如何通过设置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())")
    }
}

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())")
    }
}

我希望这对你有帮助!

相关问题