Can an INIntent property be given the value “Ask Each Time”?

梦想与她 提交于 2019-12-11 02:18:32

问题


Let's say I've defined a custom intent, called FooIntent, in an .intentdefinition file.

It has a single parameter, bar, of type Decimal, for which:
- User can supply value in Siri and Shortcuts app is active.
- Default Value is 0.

Its autogenerated class definition now looks like this:

public class FooIntent: INIntent {
    @NSManaged public var bar: NSNumber?
}

If I construct a FooIntent, set bar to nil, and pass it into a INUIAddVoiceShortcutViewController:

let intent = FooIntent()
intent.bar = nil
intent.suggestedInvocationPhrase = "Do foo"

let shortcut = INShortcut(intent: intent)

let viewController = INUIAddVoiceShortcutViewController(shortcut: shortcut!)
viewController.delegate = self
window?.rootViewController?.present(viewController, animated: true, completion: nil)

the Add to Siri modal appears with the bar parameter filled in with 0, its default value.

If, in the Add to Siri UI, I then change bar to Ask Each Time and press Add to Siri, the resulting delegate method call produces an INVoiceShortcut object that contains a nil value for bar:

func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith shortcut: INVoiceShortcut?, error: Error?) {
    if let intent = shortcut?.shortcut.intent as? FooIntent {
        print(intent.bar) // nil
    }
    controller.dismiss(animated: true, completion: nil)
}

The same is true if I set bar to Clipboard in the UI.

If I set it to a value, e.g. 42, then intent.bar correctly returns 42.

Since nil seems to represent multiple concepts for a parameter, where is the concept of Ask Each Time stored in the shortcut or intent objects?

Is there anything I can pass into INUIAddVoiceShortcutViewController such that intent.bar = <Ask Each Time>?


回答1:


Usually you control the behavior (of whether or not to continue asking for user input for a particular param) in your IntentHanlder. For example I achieved to do it this way:

FooIntentHandler: NSObject, FooIntentHandling {

    func resolveBar(for intent: FooIntent, with completion: @escaping (FooBarResolutionResult) -> Void) {
        if let bar = intent.bar as? NSNumber {

            var everythingIsFine = false

            // Any logic here.
            // You can even assign an invalid magic number in your INUIAddVoiceShortcutViewController
            // so that your compare it here to see if the user has input anything different.

            if everythingIsFine {
                completion(FooBarResolutionResult.success(with: bar))
            } else {
                // With .needsValue() Siri will always ask for user input.
                completion(FooBarResolutionResult.needsValue())
            }
        } else {
            completion(FooBarResolutionResult.needsValue())
        }
    }
}

You can also assign a valid value as the initial one, in which case Siri will accept the param value (without asking for user input) as long as you call FooBarResolutionResult.success() in your resolve method as shown above.

In short, Siri calls this resolveBar() to decide whether or not asking for user input.



来源:https://stackoverflow.com/questions/58460720/can-an-inintent-property-be-given-the-value-ask-each-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!