Create SiriKit Extensions in iOS 10

Since Siri was introduced back in 2011, iOS developers have been asking for the possibility to integrate third-party apps with it. With the release of iOS 10 during WWDC 2016, Apple finally made SiriKit available to developers.

Create SiriKit Extensions in iOS 10

There are still some restrictions on which types of applications can take advantage of Siri, but it’s a step in the right direction. Let’s take a look at what we can do with Siri.

Create SiriKit Extensions in iOS 10

For more on SiriKit and the other new features for developers in iOS 10, check out Markus Mühlberger’s course, right here on СodeHolder Tuts+.

  • Create SiriKit Extensions in iOS 10
    What’s New in iOS 10
    Markus Mühlberger

Supported Domains

To make use of SiriKit, your app has to be in one or more of the following domains:

  • VoIP calling (for example, Skype)
  • Messaging (WhatsApp)
  • Payments (Square, PayPal)
  • Photo (Photos)
  • Workouts (Runtastic)
  • Ride booking (Uber, Lyft)
  • CarPlay (automotive vendors only)
  • Restaurant reservations (requires additional support from Apple)

If your app doesn’t belong to any of these categories, unfortunately you cannot use Siri in your app at this moment. Don’t leave just yet, though, because SiriKit is very powerful, and it may gain new capabilities in the future!

Extension Architecture

A SiriKit extension is in reality composed of two types of extension. An Intents extension is required and takes care of handling the requests by the user and executing a specific task in your app (such as starting a call, sending a message, etc.).

On the other hand, an IntentsUI extension is not mandatory. You should only create one if you want to customize the user interface that Siri shows when presenting your data. If you don’t do this, the standard Siri interface will be displayed. We are going to take a look at both types of extension in this tutorial.

For your information, during WWDC 2016 Apple released two very interesting videos about SiriKit. You may want to check them out:

Example Project

We are going to build a simple app that processes payments via Siri. The goal is to successfully process the sentence “Send $20 to Patrick via TutsplusPayments”. The format of the sentence consists of an amount of money with a specific currency, the name of the payee, and the app to use to complete the transaction. We are later going to analyze the payment intent in more detail.

Initial Setup

Let’s start by creating a standard Xcode project in Swift and giving it a name. There are a few mandatory steps that you have to do before writing any code to enable your app to use Siri’s APIs.

1. Select your Target > Capabilities and enable the Siri capability. Make sure that the entitlements were created successfully in your project structure.

Create SiriKit Extensions in iOS 10

2. Open your app’s Info.plist and add the key NSSiriUsageDescription. The value must be a string explaining your usage of Siri that will be shown to the user when asked for the initial permission.

3. Select File > New > Target. In the new window presented by Xcode, under Application Extensions, choose Intents Extension. Also select the option to include a UI Extension. This will save you from later having to create another separate extension.

Create SiriKit Extensions in iOS 10

In the Info.plist file of your newly created Intents target, fully expand the NSExtension dictionary to study its contents. The dictionary describes in more detail which intents your extension supports and if you want to allow the user to invoke an intent while the device is locked.

Insert the most relevant intents at the top if you want to support more than one. Siri uses this order to figure out which one the user wants to use in case of ambiguity.

We now need to define which intents we want to support. In this example, we are going to build an extension that supports the payment intent. Modify the Info.plist file to match the following picture.

Create SiriKit Extensions in iOS 10

Here we specify that we want to handle the INSendPaymentIntent and that we require the device to be unlocked. We don’t want strangers to send payments when the device is lost or stolen!

iOS Target

The next step actually involves writing some code in the iOS app. We have to ask the user for permission to send their voice to Apple for analysis. We simply have to import the Intents framework and call the appropriate method as follows:

import UIKit
import Intents 

class ViewController: UIViewController {

    override func viewDidLoad() {
		// Ask permission to access Siri
		INPreferences.requestSiriAuthorization { authorizationStatus in
			switch authorizationStatus {
			case .authorized:
				print("Not Authorized")

The resulting dialog presented to the user during the first launch of the app will look like this.

Create SiriKit Extensions in iOS 10

This is all we have to do in our simple iOS app. Let’s get into the extensions world now!

Intents Extension

Switch to the Intents extension that we created earlier. Expand its contents in the Xcode project navigator. You’ll see just one file named IntentHandler.swift.

This file is the entry point of your extension and is used to handle any intents that Siri sends you. Siri will forward to the handler(for:) method all the intents in case your extension supports multiple types. It’s your job to check the type of the INIntent object and handle it appropriately.

The IntentHandler.swift template already contains an example implementation of a Messaging intent. Replace all the code with the following empty method so that we can walk together through each step.

class IntentHandler: INExtension {
    override func handler(for intent: INIntent) -> Any? {
        // This is the default implementation.  If you want different objects to handle different intents,
        // you can override this and return the handler you want for that particular intent.         
        return self

Each intent has an associated protocol to make sure a class implements all the required methods. Most of the protocols in the Intents framework have the same structure.

The protocol that we are going to implement is called INSendPaymentIntentHandling. This protocol contains the following required and optional methods:

  • Required:handle(sendPayment:completion:)
  • Optional:confirm(sendPayment:completion:) resolvePayee(forSendPayment:with:)

Let’s create an extension of the IntentHandler class in the same Swift file to implement the only required method.

extension IntentHandler: INSendPaymentIntentHandling {
    func handle(sendPayment intent: INSendPaymentIntent, completion: @escaping (INSendPaymentIntentResponse) -> Void) {
        // Check that we have valid values for payee and currencyAmount
 	    guard let payee = intent.payee, let amount = intent.currencyAmount else {
            return completion(INSendPaymentIntentResponse(code: .unspecified, userActivity: nil))
 	    // Make your payment!
 	    print("Sending (amount) payment to (payee)!")
        completion(INSendPaymentIntentResponse(code: .success, userActivity: nil))

This is a very basic implementation. We make sure there is a valid payee and currencyAmount to set the transaction as successful. You may not believe it, but it works already! Select the Intents scheme from Xcode and run it. When Xcode presents the usual menu to choose an app to run, select Siri.

Create SiriKit Extensions in iOS 10

When Siri starts, try to say, “Send $20 to Patrick via TutsplusPayments”. Now enjoy your first successful payment completed with your voice!

Create SiriKit Extensions in iOS 10

You can also try to test the failing case. Try to say the same sentence as before but without specifying the payee (i.e: “Send $20 via TutsplusPayments”). You’ll see that Siri will fail and present the user a button to continue the payment in your app.

Create SiriKit Extensions in iOS 10

In case Siri does not understand or is not provided with one of the optional parameters but you require a valid value, you can implement one of the resolve methods. Those methods present the user an option to give more details about the payment such as the name of payee, the exact currency amount, and even a note. With this smart architecture of the API, you as developer are presented with the possibility to easily and clearly understand your user’s request in different ways.

In a real-world application, you would create a dynamic framework that is shared between your iOS app and extensions. By making use of this architecture, you can share the same business logic in multiple targets. You won’t need to implement it multiple times, but just once and for all targets!

Intents UI Extension

In the last part of this tutorial, I am going to show you how you can customize the user interface that Siri displays.

First of all, remember to set the correct intent class that you want to handle in the Info.plist of the ExtensionUI, as we did in the previous section.

Jump into the Intents UI extension and you’ll see the template that Xcode has created for you. It contains an IntentViewController, which is a simple subclass of UIViewController that implements the INUIHostedViewControlling protocol. A Storyboard file was also created for you; open it so that we can start customizing the user interface.

Add a UIImageView as the background and a label in the center. Download the background image, import it into the Intents UI target, and set it as the image of the newly created UIImageView. Create a UILabel object and position it at the center of the view. You can easily use AutoLayout to set up the constraints in Storyboard.

Open the Assistant Editor and create an @IBOutlet for your label and call it contentLabel. The result should look like something like this:

Create SiriKit Extensions in iOS 10

Open the IntentViewController file and you’ll see a bunch of example code. You can remove everything except the configure(with:context:completion:) method that we are going to implement now. This method is called when the user interface is ready to be configured. What we have to do here is set the content of the UILabel.

class IntentViewController: UIViewController, INUIHostedViewControlling {
    @IBOutlet weak var contentLabel: UILabel!
    // MARK: - INUIHostedViewControlling
    func configure(with interaction: INInteraction!, context: INUIHostedViewContext, completion: ((CGSize) -> Void)!) {
        if let paymentIntent = interaction.intent as? INSendPaymentIntent {
            // If any of this properties is not set, use the default UI.
            guard let amount = paymentIntent.currencyAmount?.amount, let currency = paymentIntent.currencyAmount?.currencyCode, let name = paymentIntent.payee?.displayName else {
                return completion(
            let paymentDescription = "(amount)(currency) to (name)"
            contentLabel.text = paymentDescription
        if let completion = completion {
    var desiredSize: CGSize {
        return self.extensionContext!.hostedViewMaximumAllowedSize

First of all, we check that the intent object is of type INSendPaymentIntent. If it is, we also make sure that all the properties that we want to display are not nil, otherwise we simply call the completion block with a size of zero to hide our custom view. If everything goes as we expect, we create a custom string with the data that we want to show to the user and set it as the text of the contentLabel.

Run the extension again and you’ll see the new view inside Siri!

Create SiriKit Extensions in iOS 10

Siri still shows the default view. We can hide it by making our view controller conform to the INUIHostedViewSiriProviding protocol.

class IntentViewController: UIViewController, INUIHostedViewControlling, INUIHostedViewSiriProviding {
    // Previous code goes here...
    var displaysPaymentTransaction: Bool {
        return true

By returning true in the displaysPaymentTransaction variable, we tell Siri that our view controller is taking care of displaying all the necessary information to the user and that the default view can be hidden. The result is much cleaner now!

Create SiriKit Extensions in iOS 10

Note: As you can see in this picture, when specifying a different currency than US dollars, Siri correctly understands and returns the currency code to the extension. Unfortunately, the text always displays US dollars. I have reported this bug to Apple!


I hope you have enjoyed this tutorial. Siri is very powerful even if limited to some types of applications at the moment. If you plan to implement it in your own apps, make sure to market it well to your users because they may not be aware of how cool and advanced your app has become!

If you want to learn more about integrating Siri in your app, or if you want to find out about some of the other cool developer features of iOS 10, check out Markus Mühlberger’s course.

  • Create SiriKit Extensions in iOS 10
    What’s New in iOS 10
    Markus Mühlberger

Also, check out some of our other free tutorials on iOS 10 features.

  • Create SiriKit Extensions in iOS 10
    Upgrade Your App to iOS 10
    Bart Jacobs
  • Create SiriKit Extensions in iOS 10
    iOS SDK
    iOS 10: Creating Custom Notification Interfaces
    Davis Allie
  • Create SiriKit Extensions in iOS 10
    iOS 10
    Haptic Feedback in iOS 10
    Patrick Balestra