Add 3D Touch quick actions tutorial

3d touch quick actions tutorial

With the introduction of the iPhone 6S (plus), Apple added a pressure-sensitive layer to their screen.  This creates a bunch of new UX possibilities for creating apps.  It’s possible to do a hard press on an application icon and get shortcuts which take you to a specific point in your app.  For example, if you do a hard-press on the Photo’s app icon you can quickly search for an image, check the most recent images or see your favourites.  It’s also possible to make these quick actions dynamic, meaning that you can add and remove actions based on the state of your application.

3D touch quick actions
3D touch quick actions

In this tutorial I will show you how you can add these quick actions to your application icon.

Define action in Info.plist

The different options which are visible when you press on your application icon are defined in your info.plist file.

First you need to create a new row in your plist and give it the key UIApplicationShortcutItems and set the type to Array. You can now add a dictionary for every quick action.

Select the row you’ve just created and add a new row to the array, set the type to Dictionary.

Within this dictionary you have to add rows with specific keys and values.  You can choose from the following options. The ones with a * in front of the name are required.

  • * UIApplicationShortcutItemType: an unique string you choose to identify inside of your app which action has to be triggered. For example be.thenerd.my-app.create-user
  • * UIApplicationShortcutItemTitle: the string the user sees.  If the string is too long, it will be wrapped on 2 lines if there is no subtitle set (see the next key). If a subtitle is set, the string will be truncated.
  • UIApplicationShortcutItemSubtitle: optional, string which is shown to the user just below the title.
  • UIApplicationShortcutItemIconType: optional, you can use a system-defined icon (the list of keys can be found here)
  • UIApplicationShortcutItemIconFileoptional, the name of the image file in your app bundle or assets catalog. The template files to create your custom icon file can be found here.
  • UIApplicationShortcutItemUserInfooptional, a dictionary with custom data you want to use.
<array>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypeAdd</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Create new user</string>
        <key>UIApplicationShortcutItemType</key>
        <string>be.thenerd.appshortcut.new-user</string>
        <key>UIApplicationShortcutItemUserInfo</key>
            <dict>
             <key>name</key>
             <string>Frederik</string>
            </dict>
    </dict>
</array>

This will give you the following result.

3D touch quick actions
App shorcut

Get notified on selection

Alright, so how do we get notified when the user selects a shortcut?  After selection the method application:performActionForShortcutItem:completionHandler gets called.  Implement this method in your AppDelegate file.

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
    
    print("Shortcut tapped")
    
}

If you tap on the shortcut you’ll see that this message pops up in your console. But how do we know which shortcut has been tapped?

This method has 3 arguments:

  1. application: a reference to the shared UIApplication instance
  2. shortcutItem: a reference to the UIApplicationShortcutItem object
  3. completionHandler: a closure which gets executed when your quick action code completes.

Remember you have specified the UIApplicationShortcutItemType key? With that unique string you can check which action you have to run. To access this string, you just fetch the value of the type property from the shortcutItem argument.

It might be a good idea to create an enum with all possible values, so you don’t make any spelling mistakes!  I’ll create a method handleShortcut:shortcutItem in which you can check what type it is and return a boolean if the action succeeded or not.  You need this because the application:performActionForShortcutItem:completionHandler: method requires that you return a boolean via the completionHandler argument.

func handleShortcut( shortcutItem:UIApplicationShortcutItem ) -> Bool {
    print("Handling shortcut")
    
    var succeeded = false
    
    if( shortcutItem.type == "be.thenerd.appshortcut.new-user" ) {
        
        // Add your code here
        print("- Handling \(shortcutItem.type)")
        
        succeeded = true
        
    }
    
    return succeeded
    
}

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {

    print("Application performActionForShortcutItem")
    completionHandler( handleShortcut(shortcutItem) )
    
}

One more thing

There is one caveat … there is a difference between launching your application and going from an inactive state to an active state.

This means you are responsible to make sure that application:performActionForShortcutItem:completionHandler: is called conditionally if for example application:didFinishLaunchingWithOptions: has already handled the application shortcut.

So how can we do this?

We will use a boolean in application:didFinishLaunchingWithOptions: to check if we need to call application:performActionForShortcutItem:completionHandler:.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
  var performShortcutDelegate = true

  ...

}

Now we’ll have to check if the UIApplicationLaunchOptionsShortcutItemKey is available in the launchOptions dictionary argument.  If this is the case, we will store the instance of UIApplicationShortcutItem in a property so we can reference it later and set our boolean to false, because we don’t want the application:performActionForShortcutItem:completionHandler: to be called again.

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var shortcutItem: UIApplicationShortcutItem?

...
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    print("Application did finish launching with options")

    var performShortcutDelegate = true
    
    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
        
        print("Application launched via shortcut")
        self.shortcutItem = shortcutItem
        
        performShortcutDelegate = false
    }
    
    return performShortcutDelegate
    
}

Now we can safely implement applicationDidBecomeActive: and check if the shortcutItem property has been set.  If so, the app is not coming from a background state.

func applicationDidBecomeActive(application: UIApplication) {
    print("Application did become active")
        
    guard let shortcut = shortcutItem else { return }
        
    print("- Shortcut property has been set")
        
    handleShortcut(shortcut)
        
    self.shortcutItem = nil
        
}

And that’s it!

You can find the source code for this project on Github.

 

 

 

 

 

 

 

%d bloggers like this: