siri shortcut button (INUIAddVoiceShortcutButton) shows wrong title when have multiple shortcuts (NSUserActivity)

I've 2 siri shortcuts in my App. I use NSUserActivity to donate these shortcuts. I've also created 2 NSUserActivityTypes in my info.plist.

There are 2 view controllers which handle these shortcuts (1 view controller for 1 shortcut).

If I add 1 siri shortcut from 1 view controller and then go to 2nd view controller the native siri shortcut button (INUIAddVoiceShortcutButton) on 2nd view controller automatically picks the first shortcut (created from 1st view controller) and shows "Added to Siri" with suggested phrase instead of showing "Add to Siri" button. I double checked that each NSUserActivity has different identifier but still somehow its picks the wrong shortcut.

View Controller 1:

let userActivity = NSUserActivity(activityType: "com.activity.type1")
userActivity.isEligibleForSearch = true
userActivity.isEligibleForPrediction = true
userActivity.title = shortcut.title
userActivity.suggestedInvocationPhrase = suggestedPhrase

let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.contentDescription = description
userActivity.contentAttributeSet = attributes
let shortcut = INShortcut(userActivity: userActivity)
let siriButton = INUIAddVoiceShortcutButton(style: .whiteOutline)
siriButton.translatesAutoresizingMaskIntoConstraints = false
siriButton.shortcut = shortcut
self.view.addSubview(siriButton)

View Controller 2:

let userActivity2 = NSUserActivity(activityType: "com.activity.type2")
userActivity2.isEligibleForSearch = true
userActivity2.isEligibleForPrediction = true
userActivity2.title = shortcut.title
userActivity2.suggestedInvocationPhrase = suggestedPhrase

let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.contentDescription = description
userActivity2.contentAttributeSet = attributes

let shortcut = INShortcut(userActivity: userActivity2)
let siriButton = INUIAddVoiceShortcutButton(style: .whiteOutline)
siriButton.translatesAutoresizingMaskIntoConstraints = false
siriButton.shortcut = shortcut
self.view.addSubview(siriButton)

A similar thing happens when I delete the App and reinstall without deleting the shortcuts from Phone's Settings App.

Seems like its an IOS bug. I figured out a workaround for this problem. You have to create a new siri button every time the user add/edit the siri shortcut. Before creating siri button do the following things

1- Get all the voice shortcuts from INVoiceShortcutCenter by calling the function. Note that this happens asynchronously, so you need to do it some time before you need the data (e.g. in your AppDelegate). You'll also need to re-load this whenever the user adds a Siri Shortcut (probably in the INUIAddVoiceShortcutViewControllerDelegate.addVoiceShortcutViewController(_:didFinishWith:error) method).

INVoiceShortcutCenter.shared.getAllVoiceShortcuts  { (voiceShortcutsFromCenter, error) in
    guard let voiceShortcutsFromCenter = voiceShortcutsFromCenter else {
            if let error = error as NSError? {
                os_log("Failed to fetch voice shortcuts with error: %@", log: OSLog.default, type: .error, error)
            }
            return
        }
        self.voiceShortcuts = voiceShortcutsFromCenter
}

2- In View Controller-1 check if the shortcut is already added or not by iterating all the voice shortcuts

let voiceShorcut = voiceShortcuts.first { (voiceShortcut) -> Bool in
    if let activity = voiceShortcut.shortcut.userActivity, activity.activityType == "com.activity.type1" {
        return true
    }
    return false
}

3- If your voice shortcut is registered then pass the INShortcut to siri button otherwise don't set it.

if voiceShorcut != nil {
    let shortcut = INShortcut(userActivity: userActivity1)
    siriButton.shortcut = shortcut
} 

Do the same thing in Second View Controller.

INUIAddVoiceShortcutButton have many bugs in iO |Apple , https://stackoverflow.com/questions/52342934/siri-shortcut-button-​inuiaddvoiceshortcutbutton-shows-wrong-title-when-have-mu So simple. So you can't create more then 1 shortcut for your app usign NSUserActivity. update its state when you remove INVoiceShortcut from iOS Settings -> Siri Shortcuts. Implementing Siri support using NSUserActivity, intents and shortcuts Siri support can be added using an Intent and an IntentUI extension. This adds quite some overhead and is not always the easiest way in a big project, as you need shared logic between the main app and the extension.

It's iOS 12.0 bug. You can fix it by update INUIAddVoiceShortcutButton.voiceShortcut with correct value. Use KVO to observe "voiceShortcut" property and when it change assign correct value to it.

Change UI Text Tint Color inside ADAL iOS Auth, siri shortcut button (INUIAddVoiceShortcutButton) shows wrong title when have multiple shortcuts (NSUserActivity). I've 2 siri shortcuts in my App. I use  Third-party apps need to support Siri Shortcuts before you can add them to Siri. If you don't see a shortcut for a third-party app, make sure that the app is up to date and check the App Store to see if the app supports Siri Shortcuts. You can also use the Shortcuts app to create custom shortcuts that combine multiple steps across multiple apps.

I just fixed this issue myself by changing my implementation (originally based on the soupchef app) to this code sample provided by apple (https://developer.apple.com/documentation/sirikit/inuiaddvoiceshortcutbutton):

EDIT: I added code that shows how I create and pass in the shortcutObject (INShortcut) for both UserActivity and custom Intent shortcuts.

The Shortcut class is an enum that contains a computed property called intent that returns an instantiation of the custom intent.

private func addShortcutButton(shortcut: Shortcut, parentViewController: UIViewController, shortcutViewControllerDelegate: INUIAddVoiceShortcutViewControllerDelegate) {
    guard let view = parentViewController.view else { return }

    if let intent = shortcut.intent {
        shortcutObject = INShortcut(intent: intent)
    } else if let userActivity = view.userActivity {
        shortcutObject = INShortcut(userActivity: userActivity)
    }

    self.shortcutViewControllerDelegate = shortcutViewControllerDelegate
    addSiriButton(to: shortcutButtonContainer)
}

func addSiriButton(to view: UIView) {
    let button = INUIAddVoiceShortcutButton(style: .whiteOutline)
    button.translatesAutoresizingMaskIntoConstraints = false

    view.addSubview(button)
    view.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
    view.centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true

    button.addTarget(self, action: #selector(addToSiri(_:)), for: .touchUpInside)
}

// Present the Add Shortcut view controller after the
// user taps the "Add to Siri" button.
@objc
func addToSiri(_ sender: Any) {
    guard let shortcutObject = shortcutObject else { return }
    let viewController = INUIAddVoiceShortcutViewController(shortcut: shortcutObject)
    viewController.modalPresentationStyle = .formSheet
    viewController.delegate = shortcutViewControllerDelegate
    parentViewController?.present(viewController, animated: true, completion: nil)
}

ios, siri shortcut button (INUIAddVoiceShortcutButton) shows wrong title when have multiple shortcuts (NSUserActivity). I've 2 siri shortcuts in my App. I use  Soup Chef is the fictitious app from this sample code project. The project shows you how to add shortcuts and personalized phrases to Siri. With shortcuts, users can access features of your app from places such as Spotlight search, Lock Screen, and the Siri watch face. With phrases, users can speak to Siri to access your app’s features.

I've moved to intents setup now and I find that even having just one intent setup and working the INUIAddVoiceShortcutButton is not able to track my shortcut. Once phrase is recorded it shows the Added to Siri with phrase.

But every time the app relaunches the Add to Siri button shows up instead of the Added to Siri button with recorded phrase.

I have tried going by Bilal's suggestion and although I can see the INVoiceShortcutCenter showing me my shortcut as present it doesn't loaded it into the Siri button.

My code looks like this for the button itself.

 private func addSiriButton() {
    let addShortcutButton = INUIAddVoiceShortcutButton(style: .blackOutline)
    addShortcutButton.delegate = self

    addShortcutButton.shortcut = INShortcut(intent: engine.intent )
    addShortcutButton.translatesAutoresizingMaskIntoConstraints = false

    siriButtonSubView.addSubview(addShortcutButton)
    siriButtonSubView.centerXAnchor.constraint(equalTo: addShortcutButton.centerXAnchor).isActive = true
    siriButtonSubView.centerYAnchor.constraint(equalTo: addShortcutButton.centerYAnchor).isActive = true

}

I have all the protocols implement and I had a close look at the Soup app but just can't figure out what drives this inaccuracy.

Funny enough, even British Airways app developers have given up on that as their button has exactly the same fault behaviour.

Update: I've built another test project with minimal amount implementation for the Intent and the Add to Siri and Added to Siri works perfectly. I'm guessing at this point that there is something in my own apps codebase that is causing this unwanted behaviour.

update 2 Just wanted to let everyone know I have fixed the issue. Using intents works fine but there is definitely a little sensitivity in the Intents definition file itself. All I had to do is create a new intent which then was generated and that worked. Seems my initial intent was somehow corrupt but there were no errors. After creating another intent and re-assigning intent handling function to that it all worked as intended. (pun intended)

SiriKit, To delete a donated shortcut call: INInteraction.delete(with: [deleteIntentIdentifier​!] Where [deleteIntentIdentifier!] is an array of the identifiers of the shortcuts that you want Regarding the recording phrase to Siri, I copied and edited the necessary button (INUIAddVoiceShortcutButton) shows wrong title when have multiple  They can appear as Siri suggestions in Spotlight, in Notification Center, you can use them as a workflow in the Shortcuts app or ask Siri to perform the Shortcut. When tapping or asking Siri to run one of these, you (as a developer) can decide if you want to run the task in the background or inside your app.

siri shortcut button (INUIAddVoiceShortcutButton) shows wrong title when have multiple shortcuts (NSUserActivity). So we can't use the default Siri button, you  You might want to only expose your Siri Shortcut via in app interface using the Add to Siri Button or your own custom interface. This is what Apple says about donating. “ Donate a shortcut each time the user performs the action in your app. Make one, and only one, donation per action at the time the user performs the action.

Back to basics of how to add Siri Shortcuts inside your own app mix in NSUserActivity which is a simple way to get Siri interacting with your app. What happens is, you can assign a shortcut which itself has an action associated with it Apple provides INUIAddVoiceShortcutButton which is a button that  Different shortcuts with unique trigger phrases would need to be set up by the user if they wish to have multiple options available when ordering coffee from Siri. You might suggest that the shortcut is set up for a coffee with no sugar after a user places this order a few times, but once it's added to Siri, it cannot be changed without

Shortcuts can be used via Suggestions (at the right time), Voice (to use any capabilities of your app just by asking Siri) and Multi Step Shortcuts (by composing multiple shortcuts in a new one) Support for conversational shortcuts which lets users customize your Shortcut behavior; Shortcuts app redesigned and build in to iOS

Comments
  • I don't see a voiceShortcut property on INUIAddVoiceShortcutButton - is this private?
  • Okay, without even observing, I was able to fix it by just calling [addToSiriButton setValue:voiceShortcut forKey:@"voiceShortcut"] where I was once calling addToSiriButton.shortcut = voiceShortcut.shortcut;.
  • Didn't work for me on iOS SDK 12.1.
  • The problem is with multiple shortcuts. Where are you handling multiple shortcuts?
  • I have a property where I set the user activity for the shortcut I'd like to use and use it to create the INShortcut. I'll update this later with more detailed code when I get back to my dev machine.
  • Hey. I've fighting with this setup at the moment. Could you elaborate how you used the Apple provided example for UserActivity please? if let shortcut = INShortcut( userAcivity: Do you use a function to selection activity to go in here?
  • Dan, I pass in the view controller that has the donated user activity (parentViewController) and I pull the userActivity from its view. I added more code to show that.
  • Is there a way, you display "Added to Siri" without phrase below it? I see some of the app doing it but could not figure it myself.
  • Hi Rumin, I haven't seen a way to remove the text below.The text itself is only added once the phrase has been recorded to server as a reminder that you have a phrase, this is one reason Apple suggests a short memorable phrase. Another reason the text is displayed is because the whole Add To Siri Button is localisable so you can localise the "Add to Siri" and also the recorded phrase.
  • Just had another look at the INUIAddVoiceShortcutButton and it is just a subclass of the UIButton which might mean that you can set label to whatever you want, although I'm still not 100% on that. In fact the INUIAddVoiceShortcutButtonStyle is part Init that sets the button style and it is only a { get } property.
  • yeah thank you Dan! Looks like "Added to Siri" text is default implementation from Apple after you set the phrase. If I try to set the title, it overlaps that text.