Search code examples
iosswiftios12sirishortcuts

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.


Solution

  • 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.