iOS: How to open Deep Links, Notifications and Shortcuts

One tool to rule them all

Have you ever built an app, that handles Push Notifications? If your app is something more complex than a “Hello, World!” app, then, most likely, the answer is yes.

How about opening Shortcuts? When all the new iOS devices support 3d touch, this feature is becoming something more than just a nice-to-have addition.

Does your app support the Universal Links? This is a relatively new feature, that is becoming popular in the modern apps. So, if you don’t use it, you may want to start.

The good thing is that you can easily find dozens of learning materials, examples, and tutorials on each if these three topics.

But what is your app has to support all of these features? Do you really have to implement it as three separate components?

Before continue, let’s clarify the terms:

Universal Links is the way to intercept some of the URL’s and instead of handling the URL in Safari, open a specific app page. Universal links require some backend work, so we will stick to Deep Links in this tutorial. Deep Links act the similar way, but it handles the custom URL schemes. Its implementation is not much different, so it won’t be difficult to add a Universal Links support if you need it.

Shortcut is the way to launch on the specific page based on selected shortcut item when you force touch on the app icon. This feature requires the 3d-touch enabled device.

Notifications: when you tap the notification (either remote or local), the app will be launched on a specific page or do certain actions.

From this descriptions you can see, that all these three features are just the different types of the same essence: when the app handles any of them, it launching from the certain page.

Apple called this a Launching Options, that are handled by AppDelegate didFinishLaunchingWithOptions method.

However, when it comes to implementation of all launching options, it becomes confusing, and often leads to hundreds of lines of redundant code. Implementation becomes even more complicated, when the app is not launching, but entering a foreground mode. Shortcut handling, deep linking, and notification handling is happening in different delegate methods, and seem to have nothing in common.

To make if clear, I will state it once again: all these features are serving the same purpose — opening a specific app page.

The question is, how to make it all work together in a nice and clean way.

Project Setup

Before we start implementing any of launching options, create a list of pages that you want to access. Let’s say, we are building an Apartment bookings app and we want to have a quick access to the following parts:

First, create a simple project with a ViewController, Navigation title and s Switch Profile Button:

Project Setup

View Controller will have a current profile type and a mechanism to switch between profiles.

I am not using any software design patterns because this is not the part of this tutorial. In the real app, you will need to find a better structure, than just storing a ProfileType right in the ViewController.

We create activityShortcutItem and messageShortcutItem for both profile types. If the current user is a Host, we add a newListingShortcutItem. For each shortcut, we use a UIApplicationShortcutIcon (this icon will be displayed next to the shortcut title when you force-touch the app icon).

We will call this method from our ViewController: when the user switches the profile, the shortcuts will be reconfigured based on the new profile type:

This method will detect when the shortcut is triggered, and the completionHandler will tell the delegate whether to handle it or not. Again, we will not place any shortcut logic in appDelegate. Instead, we create a method in DeeplinkManager:

This method will first try to parse the shortcut item to the DeeplinkType, and then it will return the boolean value, indicating if the parsing succeeded or not. At the same time, it will save the parsed shortcut in the deeplinkType variable.

@discardableResult tells the compiler to ignore the result value if we don't use it, so we don't have an “unused result” warning

Once the shortcut is handled, the DeeplinkManager resets the current shortcut item to nil, so it won’t be used again

Run the app and test how it works in 2 scenarios: when the app launches from the closed state, and when the app is resuming from the background mode. In both cases, you should see the alert with an appropriate message:

Deep Links

The Deeplinks we are going to handle will have the following format:

deeplinkTutorial://messages/1deeplinkTutorial://request/1

Copy and save this URLs in “Notes” on your testing device. If you tap on any of the links, nothing is going to happen.

If this was a Universal Link, tapping on the link would open a browser with a link URL.

When we finish with this section, tapping the URL will open the appropriate page in our app.

AppDelegate will detect if the app was opened with deeplink URL and trigger the openUrl method:

This method will also be triggered when the app received a push notification while it is running in the foreground mode. Because we only considering the scenarios when you want to open the app on the certain page, we will not cover handling notifications in the foreground mode.

Once the shortcut is handled, the DeeplinkManager resets the current shortcut item to nil, so it won’t be used again

Using this approach, you can easily add or modify any of the items without significant code changes. And what is more important, you can parse any deeplink using the appropriate parser. For example, to add “New Request” in Notification handler, you only need to modify handleNotification method in NotificationParser: