Starting with siriKit — part 2/2

Bruno Cardoso Ambrosio
Academy@EldoradoCPS
4 min readMar 25, 2020

More than add it, we need to manage it

In the last post (part 1) we learned how to create an “add to siri” button and how to solve the crop issue. In this post we gonna implement the edit shortcut modal and fix the shortcut behavior to open the SecondViewController.

1 — Add the delegate

Just as there is an add delegate, there is an edit/remove delegate and we gonna implement it now. Open the SecondViewController and, at the end of file, add the code below:

We don’t need to do anything beside call the modal dismiss, but before each dismiss we could do anything we want.

2 — Create class SiriUtil

The next steps would implement a solution that i already had done, but when i started to write here i’ve found a very much more scalable solution that allow us to reuse our code, so we will implement it. Create a new swift file called “SiriUtil.swift”. This part uses a lot of closures.

We need the import of IntentsUI

import IntentsUI

And the code below shows our class, we have two functions into it, the first receive a Shortcut and search in the VoiceShortcutCenter for a VoiceShortcut that match, if it exists.

There are Shortcuts and VoiceShortcuts, the first is a shortcut suggestion of our app, the second is a shortcut that is already added to siri and theVoiceShortcutCenter is the siri voiceShortcuts manager.

The first function into the class is used by the second that has the responsibility of set which ViewController will be opened (the add or edit modal) and call the open closure to really open it.

As the voiceShortcut is a shortcut already added, if it is nil it open the add modal, else open the edit modal.

3 — Editing addToSiri function

We have a function with the responsibility to open the siri modal, we need now to adapt it to use our SiriUtil functions to open the right modal (to add or to edit/remove). So open the SecondViewController and go to addToSiri function, delete all code below the guard let as shown below: (you can replace your version of the func to that too)

@objc func addToSiri(sender: Any) {guard let sender = sender as? INUIAddVoiceShortcutButton, let shortcutFromButton = sender.shortcut else { return }// TODO: we gonna add the open siri logic here}

Now we need to add the code that calls the SiriUtil, replace the TODO inside the function with the block below:

SiriUtil.openShortcutViewController(caller: self, shortcut: shortcutFromButton) { (shortcutViewController) in//as we are on a closure, we need to call the main thread to present the modal
DispatchQueue.main.async {
self.present(shortcutViewController, animated: true, completion: nil)
}
}

We call the function passing a closure that shows how it will open the viewController received.

As we are inside a closure, we need to call the main thread to present the modal.

Building & running is possible to see the “add to siri” button working with both the add and edit modal.

Shortcut behavior

Everything is beautiful, except by the shortcut behavior, it’s still not opening the SecondViewController (that is its purpose). Till the end this post it will be fixed (this step only works on iOS 13 or more, because we use the SceneDelegate — before the iOS 13 you will need to adapt this solution to AppDelegate)!

Open the main.storyboard, select the navigation controller and open the identity inspector. Set its Storyboard ID to “navController”, then select the SecondViewController and set its Storyboard ID to “second”.

Then open the SceneDelegate and add the auxiliary code bellow:

The func executed by the shortcut

This function load the navigation controller and the SecondViewController and starts the app as you have already navigated to the secondViewController. Now add the second auxiliary code:

This one has the responsibility to be called by the app when it needs to interpret a NSUserActivity. It test all our existent activityTypes enum and if there is a match, it does what the activity needs (in this case, to open SecondViewController) or else it continues the normal flow and open home (viewController).

To finish, we need to call this function at two SceneDelegate points, the first is at a scene function that we will implement now:

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
dealWithUserActivities(userActivity: userActivity, isContinuing: true)
}

This function is always called when the app is returning from the background by the effect of a shortcut, that’s why we are passing true to isContinuing.

Then we need to implement the function scene(_:willConnectTo:options). Right below the var window you can replace the whole function by the next code:

This function is always called when the app starts normally. If it involves an activity, our function is called, but we say that the app was not on background (isContinuing = false).

Build & run your app. You can test it putting the app on background (if you are using the simulator, there is a shortcut: command⌘+shift⇧+h), call the app by our shortcut (siri test) and it should open the app on the correct screen. You can also kill the app and start it by the shortcut and it should reproduce the same behavior as you can see on the GIF below.

Link to the final version here

--

--

Bruno Cardoso Ambrosio
Academy@EldoradoCPS

Brazilian iOS Developer, Java & Technology lover and psychology enthusiast