Leonardo Maia Pugliese
Holy Swift

Holy Swift

Create Home Screen Quick Actions in Swift

Create Home Screen Quick Actions in Swift

More ways to experience your apps!

Leonardo Maia Pugliese's photo
Leonardo Maia Pugliese

Published on Nov 18, 2021

7 min read

Subscribe to my newsletter and never miss my upcoming articles

Hallo dammes en heren, Leo hier.

Today we'll talk about Home Screen quick actions. They are a really good experience created by Apple from iOS 13 and above where you can have access to whatever feature that the app provide from your Home Screen.

Imagine that you have a e-commerce app and you can give access to the shopping cart directly from the Home Screen of the app (not using widgets, of course). Or imagine you have a weather app and you want the user open the app already in the rain radar. There is an infinite number of possibilites!

There's two ways to setup this into your app and we will explore both here.

The Painting

The painting is a 1862 piece called Path Towards a House in the Countryside from Jean-Baptiste-Camille Corot. A pivotal figure in landscape painting, Jean-Baptiste Camille Corot was an influential and prolific artist, producing over 3,000 works during his lifetime, and inspiring countless numbers of forgeries and copies.

He focused on two types of landscapes, historical landscapes, containing ancient and mythological creatures, and realistic landscapes, mostly of Northern Europe, with faithful renditions of flora and fauna, often mixing the two genres together.

I chose this painting because it shows a path in the woods. This remember me that quick actions menu is another path to your apps features.

The Problem

You want to add a Home Screen Quick Action to your app.

For those who aren't familiar with the term and the feature. When you do a long press in any app in the Home Screen, some options will appear. The good thing is that you can add more action to it as shortcut to features in your apps.

The Home Screen Quick Action looks like the image below:

Screenshot 2021-11-17 at 08.23.41.png

Let's start coding.

Two types of Quick Actions

Apple provides you with two types of home menu quick actions. One is called Static Quick Actions and the other Dynamic Quick Actions.

The static quick actions as the name suggest can't change within the installation. That means that all actions you setup this way will be the same until your next app install. This is useful when you already know what features you want to provide from home quick actions menu.

The other type is the Dynamic Quick Actions. This actions you can change in runtime, for example: imagine that you have a weather app and the user can have favorite cities, you can show the favorites cities in the quick actions menu. This means that even if the user remove all cities or add a lot of cities iOS will take care to show those favorites in the quick actions menu.

Making a Static Quick Action

Create a new Xcode iOS project anywhere in Mac.

Now go to the Info.plist file and we will add some infos to it.

<key>UIApplicationShortcutItems</key>
<array>
    <dict>
        <key>UIApplicationShortcutItemType</key>
        <string>SearchAll</string>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypeSearch</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Search All</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>This is a subtitle!</string>
    </dict>
</array>

Now you can already build and run your app and do a long press in the Home Screen, and you can already see the new option in the menu:

Screenshot 2021-11-17 at 08.23.41.png

But if you tap it, nothing happens. Now we need to wire up everything in the code to intercept this call.

Responding to quick action have two types. One is when the app is completely closed ( not loaded / in background ), and other is when the app is in background.

  • When the app is completely closed we can intercept safe the quick action in the SceneDelegate to use when the app will become active:
    var savedShortCutItem: UIApplicationShortcutItem?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }

        if let shortcutItem = connectionOptions.shortcutItem { // get the shortCutItem here
            savedShortCutItem = shortcutItem
        }
    }

    // Verify when user is opening your app with the home menu quick Action
    func sceneDidBecomeActive(_ scene: UIScene) {
        if savedShortCutItem != nil {
            _ = handleShortCutItem(shortcutItem: savedShortCutItem)
        }
    }
  • When the app is loaded/background you should add this function to the SceneDelegate to be able to intercept the shortcut Item:
    func windowScene(_ windowScene: UIWindowScene,
                     performActionFor shortcutItem: UIApplicationShortcutItem,
                     completionHandler: @escaping (Bool) -> Void) {
        print(shortcutItem)
    }

To test add this function to your SceneDelegate:

    func showAlert(message: String) {
        let alertController = UIAlertController(title: "Quick Action", message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Close", style: .default, handler: nil))
        window?.rootViewController?.present(alertController, animated: true, completion: nil)
    }

And show alerts on both situations, when you have and don't have your app loaded:

    func sceneDidBecomeActive(_ scene: UIScene) {
        if let savedShortCutItem = savedShortCutItem {
            showAlert(message: "\(savedShortCutItem.description) + from start")
        }
    }

    func windowScene(_ windowScene: UIWindowScene,
                     performActionFor shortcutItem: UIApplicationShortcutItem,
                     completionHandler: @escaping (Bool) -> Void) {
        showAlert(message: "\(shortcutItem.description) + from background")
    }

Build and run, put the app in background and tap the quick action menu in the app:

Screenshot 2021-11-18 at 08.43.48.png

Now close the app. Tap the quick action menu in the app again, you should see:

Screenshot 2021-11-18 at 08.45.44.png

Dynamic Quick Actions menu

As above stated when using dynamic quick actions menu, you should set programatically all of them. In this matter, you can set them anywhere in the app.

However, the Apple documentation recommends you setting the quick actions on the sceneWillResignActive(_:) function of the scene delegate. The argument is that during a background state is a good time to refresh the quick menu action because is the last action the system does before returns to the Home Screen.

Let's imagine that you have a bunch of favorite cities. And you want to dynamically show them in the quick action menu. Let's create those in SceneDelegate:

    var favoriteCities = ["Haarlem","San Andreas", "Saint Field's Bernard"]

    func sceneWillResignActive(_ scene: UIScene) {
        let application = UIApplication.shared
        application.shortcutItems = favoriteCities.map { city -> UIApplicationShortcutItem in
            return UIApplicationShortcutItem(type: city,
                                             localizedTitle: city,
                                             localizedSubtitle: "Favorite City",
                                             icon: UIApplicationShortcutIcon(systemImageName: "map"),
                                             userInfo: ["CityIdentifier": city as NSSecureCoding])
        }
    }

Of course if was a production app, you should get this from a service or storage within your app. This is just a simplification.

Some remarkable things about creating shortcutItems:

  1. You can have a localised Title and Subtitle.
  2. You can retrieve the userInfo using: shortcutItem.userInfo?["CityIdentifier"] as? String
  3. You have two ways to set the icon, SF Symbol or template image.

And when using the quick actions menu, you can see your favorites cities:

Screenshot 2021-11-18 at 09.03.19.png

Choosing the Icon in the Menu

You can set quick action icons with UIApplicationShortcutIcon class and they can be done in two different ways: SF Symbol or with a template image from this enum.

With a template image name enum:

UIApplicationShortcutIcon(type: .favorite)

With an SF Symbol name:

UIApplicationShortcutIcon(systemImageName: "star.fill")

Keep in mind that you have to check the SF Symbol version compatibility with the App minimum target.

Scene Delegate Full code

Below is the complete scene delegate code. Remember that you still need to do the Info.plist to work with static quick actions menu items.

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    var savedShortCutItem: UIApplicationShortcutItem?
    var favoriteCities = ["Haarlem","San Andreas", "Saint Field's Bernard"]

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }

        if let shortcutItem = connectionOptions.shortcutItem {
            savedShortCutItem = shortcutItem
        }
    }

    func sceneDidDisconnect(_ scene: UIScene) {
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        if let savedShortCutItem = savedShortCutItem {
            showAlert(message: "\(savedShortCutItem.description) + from start")
        }
    }

    func windowScene(_ windowScene: UIWindowScene,
                     performActionFor shortcutItem: UIApplicationShortcutItem,
                     completionHandler: @escaping (Bool) -> Void) {
        showAlert(message: "\(shortcutItem.description) + from background \(shortcutItem.userInfo?["CityIdentifier"] as? String)")
    }

    func sceneWillResignActive(_ scene: UIScene) {
        let application = UIApplication.shared
        application.shortcutItems = favoriteCities.map { city -> UIApplicationShortcutItem in
            return UIApplicationShortcutItem(type: city,
                                             localizedTitle: city,
                                             localizedSubtitle: "Favorite City",
                                             icon: UIApplicationShortcutIcon(systemImageName: "map"),
                                             userInfo: ["CityIdentifier": city as NSSecureCoding])
        }
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
    }

    func showAlert(message: String) {
        let alertController = UIAlertController(title: "Quick Action", message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Close", style: .default, handler: nil))
        window?.rootViewController?.present(alertController, animated: true, completion: nil)
    }
}

Summary

Today we study a how you can add quick menu actions to your apps. We learn there's two ways to show them and why to use each one. This feature is important because it gives multiple ways to your users to navigate through your apps and increasing the usability of your apps.

That's all my people, I hope you liked as I enjoyed write this article. If you want to support this blog you can Buy Me a Coffee or just leave a comment saying hello. You can also sponsor posts and I'm open to writing freelancing! Just reach me in LinkedIn or Twitter for details.

Thanks for the reading and... That's all folks.

credits: image

Did you find this article valuable?

Support Leonardo Maia Pugliese by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this