Xcode Siri Intents:如何将变量从 Intent Handler 传递到 IntentUI ViewController 而无需将其包含在响应中

Xcode Siri Intents: How to pass a variable from Intent Handler to IntentUI ViewController without including it in the response

我需要将一个变量从 Intent Handler 传递到 IntentViewController 而无需将其包含在响应中,以便它显示在自定义 UI 中而无需 Siri 说出来。

到目前为止,我只能使用这样的响应来传递它们:

completion(GetTimesIntentResponse.success(name: "SomeName", time: "5:40", location: LatestLocation.City))

然而,这意味着 Siri 必须将此作为响应的一部分。我想要的只是 location 显示在标签中(在自定义 UI 中)而无需 Siri 读出它。

我没能找到直接执行此操作的方法,但是解决方法是将变量保存到 Intent Handler 中的 Core Data 并在 IntentViewController 中获取它们。这只是一种解决方法,但对我来说很有效,因为我只需要传递一个变量,并且已经将它存储在应用程序其他地方的核心数据中。

如果您想访问您的意图 属性,您可以在 IntentViewController 中执行此操作:

func configureView(for parameters: Set<INParameter>, of interaction: INInteraction, interactiveBehavior: INUIInteractiveBehavior, context: INUIHostedViewContext, completion: @escaping (Bool, Set<INParameter>, CGSize) -> Void) {

    let intent = interaction.intent as! YourIntent
    // let foo = intent.yourProperty // access your property from your intent
}

我希望这就是你的意思。

来自 INUIHostedViewControlling 文档:

An Intents UI app extension works in tandem with a corresponding Intents app extension. The Intents app extension handles the intent and provides a response that includes data from your app. The view controller in your Intents UI app extension receives that data in the form of an INInteraction object and uses it to configure its view.

因此,在您的 IntentHandler 中:

func handle(intent: GetTimesIntent, completion: @escaping (GetTimesIntentResponse) -> Void) {
    let activity = NSUserActivity(activityType: "com.your_company.your_identifier.get_times")
    activity.userInfo?["times_time"] = "5:40"
    activity.userInfo?["times_location"] = LatestLocation.City
    let response = GetTimesIntentResponse(code: .success, userActivity: activity)
    completion(response)
}

并且在您的 IntentViewController 中:

func configureView(for parameters: Set<INParameter>, of interaction: INInteraction, interactiveBehavior: INUIInteractiveBehavior, context: INUIHostedViewContext, completion: @escaping (Bool, Set<INParameter>, CGSize) -> Void) {
    let data = interaction.intentResponse?.userActivity?.userInfo
    let time = data?["times_time"] as? String ?? "No time"
    let location = (data["times_location"] as? LatestLocation.City)?.name ?? "No city"
    label.text = "\(location) at \(time)"

    completion(true, parameters, self.desiredSize)
}