Add Quick Actions to SwiftUI App
Hello, we will be discussing Quick Actions in this article. If you haven’t heard of Quick Actions before, we can start by summarizing it.
When you press and hold an app on the home screen of your iPhone, the options you see in the menu that appears above the app, apart from the iOS system items, are specific to that app and are called Quick Actions. They allow you to navigate to a specific page or feature within the app before actually opening the app.
We can create the Quick Actions buttons that we will show to the user either statically from our info.plist file or dynamically while running from the SceneDelegate. Let’s examine these methods step by step.
To add Quick Actions Statically
Firstly, let’s start by adding a key and dictionary to the info.plist
file in a static way. To make it easier to work, I open the info.plist
file by right-clicking and selecting "Open As > Source Code". I define the key as "UIApplicationShortcutItems".
Inside UIApplicationShortcutItems, there is an array key, and this array consists of dictionaries.
Later on, I will complete my operations on the info.plist by adding dictionaries inside the array, each taking the necessary parameters. Here, we can summarize the keys we can define within UIApplicationShortcutItems as follows.
- UIApplicationShortcutItemType*: This is a required key that is passed to our application when the user invokes the corresponding quick action. Your application can use this key to distinguish between types of quick actions and subsequently perform actions based on the received types. You don’t need to register your quick action types.
- UIApplicationShortcutItemTitle*: This is a required key used as the name of the quick action displayed to the user on the Home Screen. It is localizable.
- UIApplicationShortcutItemSubtitle: This is an optional key that is displayed just below the corresponding title string on the Home Screen to provide additional information to the user.
- UIApplicationShortcutItemIconType: This is an optional key specifying the type of icon in the library provided by Apple. The icon is displayed in the quick actions menu on your app’s Home Screen along with the title of the action.
- UIApplicationShortcutItemIconFile: This is an optional key to use if you want to provide the icon for the quick action from your own assets rather than the system’s library.
- UIApplicationShortcutItemUserInfo: This is an optional dictionary defined by the application. With this key, app developers can pass application version information when creating shortcuts and perform custom actions based on this information.
After completing this process, you can run your project and, by pressing and holding on the home screen, you will be able to see the quick actions item on the screen. You can also find all the relevant keys here.
To add Quick Actions Dynamically
If we want to add Quick Action items dynamically, we need to do this at runtime. We will add these items dynamically by accessing the shared instance of UIApplication and adding them to the .shortcutItems array. Similar to the keys we discussed earlier, we will be adding objects of type UIApplicationShortcutItem. For these objects, we must provide the parameters type and title as mandatory parameters.
Once we have prepared our function, the question arises as to where we should call this function. If our application were a UIKit application, we could have called it within the sceneWillResignActive
method in the SceneDelegate. However, here we will take a different approach.
Since this method needs to be called when the application goes to the background, we will define an environment variable that will allow us to understand when the application goes to the background. This variable indicates the state of the application. The .scenePhase
is an environment variable provided by Apple, similar to .dismiss
and .colorScheme
.
@Environment(\.scenePhase) var scenePhase
To trigger our method when the scene enters the .background
state, we can define an .onChange
modifier on the WindowGroup
in the App
struct. This allows us to observe changes in the scenePhase
.
The reason for specifically performing this task in the background is explicitly mentioned in the Apple documentation.
Set dynamic screen quick actions at any point, but the sample sets them in the
sceneWillResignActive(_:)
function of the scene delegate. During the transition to a background state is a good time to update any dynamic quick actions, because the system executes this code before the user returns to the Home Screen.
As mentioned here, updating dynamically added quick actions in the background state is the optimal time.
After these processes, if we take a look at our application on the home screen:
Determining the Functions of Quick Actions Buttons
Up until this step, despite avoiding AppDelegate and SceneDelegate, at this point, we now need to add it to our application. Because when the user taps on the application, there are two scenarios we need to handle:
- When the application is completely closed and opened from scratch — AppDelegate — configurationForConnecting
- If the application is opened while in the background — SceneDelegate — performActionFor
we will handle it through.
Let’s get started right away. First, let’s add AppDelegate. After creating the AppDelegate class, go to the @main App struct of our SwiftUI app, and before the .scenePhase variable, define our delegate.
class AppDelegate: NSObject, UIApplicationDelegate {
}
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
Afterwards, by creating a SceneDelegate, we configure it within the AppDelegate.
After completing our delegates, I continue the process by writing a Quick Actions manager. This manager has a singleton structure and takes a value from an enum I prepared of type QuickAction. Through the handle() function inside, it decides based on the type of UIApplicationShortcutItem using an if condition.
Here, you can establish different logics or a generic structure based on your needs. I followed this approach for simplicity and clarity in this story.
Later on, I call this manager in the necessary places within AppDelegate and SceneDelegate. We mentioned the places where it should be called. Below, you can see the QuickActionsManager we prepared first and the places where the handle function of this manager is called inside the delegate, sequentially.
Now it’s time to open our page through this manager, make the necessary preparations, and perform navigation based on the quickAction variable defined as published inside the manager. For this, let’s prepare a simple view and listen to the quickAction variable inside the manager using an .onChange modifier. Also, let’s handle the data in the .onAppear modifier when the application is opened from a closed state.
With this structure we prepared, the quickAction value inside the manager will be listened to, and based on this value, the navigationValue will be set, enabling the navigation process.
Important Note: The reason for using deprecated NavigationLink structures here is to avoid delving into any coordinator events and complicating things. As mentioned earlier, you can implement your own logics based on the flow of your application.
Now, let’s take a look at our application:
In summary, using Quick Actions in a SwiftUI application is as practical as outlined here. See you in another article! Happy coding.
You can access the source code here.