How to Make Static and Dynamic Home Screen Quick Actions in SwiftUI
Tags: swift, ios, swiftui
Published: 2020-11-05 00:06:36

---
title: How to Make Static and Dynamic Home Screen Quick Actions in SwiftUI
published: true
description: 
tags: #swift #ios #swiftui
//cover_image: https://direct_url_to_image.jpg
---

<!-- wp:image {"align":"center","id":1271,"width":295,"height":456,"sizeSlug":"large","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img src="https://swifttomcom.files.wordpress.com/2020/11/screen-shot-2020-11-04-at-6.13.48-pm.png?w=558" alt="" class="wp-image-1271" width="295" height="456"/></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Home screen quick actions are shortcuts for users to navigate into different parts of our app. In this post we are going to see how we can add these quick actions into our SwiftUI project. The two different types of quick actions we can use is <strong>static quick actions</strong> and <strong>dynamic quick actions</strong>. Let's start by taking a look at how we can add static quick actions to our project.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As the name implies <strong>static quick actions</strong> do not change. If we want to add <strong>static quick actions</strong> to our project we will need to implement it in our <strong>info.plist</strong>. If we right click on the <strong>info.plist</strong> and go to <strong>&gt; &nbsp;Open As&nbsp;&gt; Source Code</strong> and at the bottom before the last <strong>&lt;/dict&gt;</strong> add the following code below.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">	&lt;key>UIApplicationShortcutItems&lt;/key>
	&lt;array>
		&lt;dict>
			&lt;key>UIApplicationShortcutItemType&lt;/key>
			&lt;string>AddAction&lt;/string>
			&lt;key>UIApplicationShortcutItemIconType&lt;/key>
			&lt;string>UIApplicationShortcutIconTypeAdd&lt;/string>
			&lt;key>UIApplicationShortcutItemTitle&lt;/key>
			&lt;string>Add&lt;/string>
			&lt;key>UIApplicationShortcutItemSubtitle&lt;/key>
			&lt;string>Add Item&lt;/string>
		&lt;/dict>
	&lt;/array>
</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p> </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p id="cf3d">In the code above we are using <strong>UIApplicationShortcutItems</strong> to create an add button for our quick action shortcuts. Our shortcut items can be found inside an array of a dictionary. In each dictionary a&nbsp;<strong>UIApplicationShortcutItemType</strong>&nbsp;and&nbsp;<strong>UIApplicationShortcutItemTitle</strong>&nbsp;are needed to make our static shortcut. <strong>UIApplicationShortcutItemType<em> </em></strong>is a string that represents what kind of quick action we want in our app. <strong>UIApplicationShortcutItemTitle</strong> is the title or name of our quick action button.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p id="5a73">If you want to learn more about <strong>UIApplicationShortcutItem</strong>'s check out the Apple&nbsp;<a href="https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW36">documentation</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p id="c0e2">Now if you run the app and then go to the home screen we can test our quick action. On the home screen if we tap and hold on our app icon we should see the “Add” quick action button pop up on our home screen.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now that we made a static quick action let's move on to adding a dynamic quick action button.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To make a dynamic quick action we will need to add them in the <strong>App</strong> struct also known as the entry point of our app. This file can be located in the navigator and is usually named after your project name followed by the word <strong>App</strong>. In this example it will be in the <strong>QuickActionSwuiftUIBlogApp.swift</strong> file. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The reason we need to create our quick action buttons in this file is because these buttons need to be made at specific point in the apps life cycle. Apples documentation recommends that we create dynamic quick actions when the app is moving to the background.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">import SwiftUI

@main
struct QuickActionSwuiftUIBlogApp: App {
    @Environment(\.scenePhase) var lifeCycle
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: lifeCycle) { (newLifeCyclePhase) in
            switch newLifeCyclePhase {
            case .active :
                print("App is active")
            case .inactive:
                print("App is inactive")
            case .background:
                print("App is going to the Background")
                // This will add our dynamic quick actions when our app is sent to the background on our device
                addQuickActions()
            @unknown default:
                print("default")
            }
        }
    }
    
    func addQuickActions() {
        UIApplication.shared.shortcutItems = [
            UIApplicationShortcutItem(type: "Tweet", localizedTitle: "Tweet"),
            UIApplicationShortcutItem(type: "Call", localizedTitle: "Call"),
            UIApplicationShortcutItem(type: "Message", localizedTitle: "Message"),
            UIApplicationShortcutItem(type: "Saved", localizedTitle: "Saved"),
        ]
    }
}</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>As you can see in the code above we created some dynamic shortcuts buttons in our <strong>addQuickActions()</strong> function. We call the <strong>addQuickActions()</strong> function to make our dynamic buttons when our app goes into the background state. We know when our app goes to the background by using the <strong>.onChange</strong> modifier with our <strong>@Environment(\.scenePhase) var lifeCycle</strong> variable. For a deeper dive please check out the <a href="https://developer.apple.com/documentation/uikit/menus_and_shortcuts/add_home_screen_quick_actions">Apple documentation</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now if we rerun our app and long press on our app icon we should see our static quick action button with our dynamic quick action buttons underneath. You may also notice that one of our quick buttons doesn't show up in the quick action sheet. This is because Apple will only show a maximum of 4 quick actions at a time. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next we will go back into our <strong>addQuickActions()</strong> function and add some more code.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">    func addQuickActions() {
        var tweetuserInfo: [String: NSSecureCoding] {
                    return ["name" : "tweet" as NSSecureCoding]
                }
                var calluserInfo: [String: NSSecureCoding] {
                    return ["name" : "call" as NSSecureCoding]
                }
                var messageuserInfo: [String: NSSecureCoding] {
                    return ["name" : "message" as NSSecureCoding]
                }
                var saveduserInfo: [String: NSSecureCoding] {
                    return ["name" : "saved" as NSSecureCoding]
                }
        
        UIApplication.shared.shortcutItems = [
            UIApplicationShortcutItem(type: "Tweet", localizedTitle: "Tweet", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .compose), userInfo: tweetuserInfo),
            UIApplicationShortcutItem(type: "Call", localizedTitle: "Call", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .audio), userInfo: calluserInfo),
            UIApplicationShortcutItem(type: "Message", localizedTitle: "Message", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .message), userInfo: messageuserInfo),
            UIApplicationShortcutItem(type: "Saved", localizedTitle: "Saved", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .love), userInfo: saveduserInfo),
        ]
    }</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>The example above will help us to identify each quick action button with a name key. This will allow us to know which of our quick actions was pressed this way we can have our app react according to what quick action the user has tapped. We will attach these new variables we created to the <strong>userInfo</strong> parameter of our <strong>UIApplicationShortcutItem</strong>. Above we also added icons to the shortcut items so we don't just have dots as icon placeholders.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now let's add two global variables above our <strong>@main</strong> in our <strong>App</strong> file. These variables will help us to pass our users input along to different areas of our app depending on which quick action we press. </p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">var shortcutItemToHandle: UIApplicationShortcutItem?
let quickActionSettings = QuickActionSettings()</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>Next we will need to add two more functions below our <strong>addQuickActions()</strong> function. </p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
            if let shortcutItem = options.shortcutItem {
                shortcutItemToHandle = shortcutItem
            }
            
            let sceneConfiguration = UISceneConfiguration(name: "Custom Configuration", sessionRole: connectingSceneSession.role)
            sceneConfiguration.delegateClass = CustomSceneDelegate.self
            
            return sceneConfiguration
        }
    }

    class CustomSceneDelegate: UIResponder, UIWindowSceneDelegate {
        func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
            shortcutItemToHandle = shortcutItem
        }
    }</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>In the code above we added an <strong>Appdelegate</strong> method and a <strong>Scenedelegate</strong> method to handle what happens to our quick action buttons at different parts of the life cycle of our app. What these two class methods are doing is handling if the app is closed we want it to open our application and if our app is in the background to handle a quick action if the user taps on it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p id="423c">Now that we have set up our quick action buttons we will want them to do something when a user taps on them. We want the user to be able to navigate to the specific section they tapped on in the home screen shortcut. This means that in our <strong>newLifeCyclePhase</strong> switch statement in our<strong> .active </strong>case we will need to perform an action. Let's take a look at how we implement this in the code below.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(quickActionSettings)
        }
        .onChange(of: lifeCycle) { (newLifeCyclePhase) in
            switch newLifeCyclePhase {
            case .active :
                print("App is active")
                guard let name = shortcutItemToHandle?.userInfo?["name"] as? String else { return }
            case .inactive:
                print("App is inactive")
            case .background:
                print("App is going to the Background")
                // This will add our dynamic quick actions when our app is sent to the background on our device
                addQuickActions()
            @unknown default:
                print("default")
            }
        }
    }
</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>Above we added a <strong>guard let</strong> variable to our <strong>.active</strong> case. This will check to see if we have a name attached to the button the user pressed on the quick action shortcuts.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now that we set that up we will go into the <strong>ContentView.swift</strong> and we are going to make a simple list view that will correspond to our quick action dynamic buttons. This will also be where we setup a observable variable to see which button has been pressed from our App file and react by bringing our user to that view in the app. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Our <strong>ContentView.swift</strong> file should have the following code in it.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">import SwiftUI

struct ContentView: View {
    @EnvironmentObject var quickActionSettings: QuickActionSettings
    @State var selectedAction: Int?

    var body: some View {
            NavigationView {
                List {
                    ForEach(0..&lt;allQuickActions.count) { index in
                        NavigationLink(destination: DetailView(name: allQuickActions[index].name), tag: allQuickActions[index].tag, selection: $quickActionSettings.quickAction) {
                            Text(allQuickActions[index].name)
                        }
                    }
                }
                .listStyle(SidebarListStyle())
                .navigationBarTitle("Quick Actions")
            }
        }
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

    struct QuickActionModel : Identifiable {
        let id = UUID()
        let name: String
        let tag: QuickActionSettings.QuickAction
    }

    let allQuickActions = [
        QuickActionModel(name: "Tweet", tag: .details(name: "tweet")),
        QuickActionModel(name: "Call",tag: .details(name: "call")),
        QuickActionModel(name: "Message", tag: .details(name: "message")),
        QuickActionModel(name: "Saved", tag: .details(name: "save")),
    ]
</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>As you can see in the example we added a <strong>@EnvironmentObject</strong> to track which quick action our user has tapped from our quick actions on the home screen. We also setup a simple list view with all of our dynamic quick action buttons. We created a <strong>QuickActionModel</strong> struct with a name and a tag and created an array of quick actions so that we can segue to the detail view depending on which quick action was tapped.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next we will need to make a new SwiftUI file called <strong>DetailView</strong>. In this file add the following code to make a simple view for our list view buttons to segue too. This detail view will just show the name of the button we selected.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">import SwiftUI

struct DetailView: View {
    var name: String
    
    var body: some View {
        Text("\(name)!")
            .navigationBarTitle(name)
    }
}</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>Now we will make another swift file and name this one <strong>QuickActionSettings</strong>. This will be our observable object so we can keep track of which quick action was pressed.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">import Foundation

class QuickActionSettings: ObservableObject {
    
    enum QuickAction: Hashable {
        case home
        case details(name: String)
    }
    
    @Published var quickAction: QuickAction? = nil
}</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>Here we are using a <strong>QuickAction</strong> enum to see if the name value changes. If it does change it will trigger our navigation link in our content view to segue to the quick action the user has tapped.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Lastly let's go back to our App file and add our <strong>.enviormentObject</strong> to our <strong>ContentView()</strong> in our WindowGroup like below.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">WindowGroup {
            ContentView()
                // We will use this modifier below to pass along which quick action that was pressed
                .environmentObject(quickActionSettings)
        }</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>We also need to update our code inside of our <strong>.active</strong> case. Here we will add another switch statement that will check the names associated with our quick actions buttons. We will then take this name variable and pass it along our <strong>quickActionSettings.quickAction</strong> so the rest of our app can update. Our final <strong>QuickActionSwuiftUIBlogApp</strong> file should look like the code below.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code -->
<pre class="wp-block-syntaxhighlighter-code">import SwiftUI

let quickActionSettings = QuickActionSettings()
var shortcutItemToHandle: UIApplicationShortcutItem?

@main
struct QuickActionSwuiftUIBlogApp: App {
    @Environment(\.scenePhase) var lifeCycle
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                // We will use this modifier below to pass along which quick action was pressed
                .environmentObject(quickActionSettings)
        }
        .onChange(of: lifeCycle) { (newLifeCyclePhase) in
            switch newLifeCyclePhase {
            case .active :
                print("App is active")
                guard let name = shortcutItemToHandle?.userInfo?["name"] as? String else { return }
                switch name {
                               case "tweet":
                                   print("tweet is selected")
                                   quickActionSettings.quickAction = .details(name: name)
                               case "call":
                                   print("call is selected")
                                   quickActionSettings.quickAction = .details(name: name)
                               case "message":
                                   print("message is selected")
                                   quickActionSettings.quickAction = .details(name: name)
                               case "saved":
                                   print("saved is selected")
                                   quickActionSettings.quickAction = .details(name: name)
                               default:
                                   print("default ")
                               }
            case .inactive:
                print("App is inactive")
            case .background:
                print("App is going to the Background")
                // This will add our dynamic quick actions when our app is sent to the background on our device
                addQuickActions()
            @unknown default:
                print("default")
            }
        }
    }
    
    func addQuickActions() {
        var tweetuserInfo: [String: NSSecureCoding] {
                    return ["name" : "tweet" as NSSecureCoding]
                }
                var calluserInfo: [String: NSSecureCoding] {
                    return ["name" : "call" as NSSecureCoding]
                }
                var messageuserInfo: [String: NSSecureCoding] {
                    return ["name" : "message" as NSSecureCoding]
                }
                var saveduserInfo: [String: NSSecureCoding] {
                    return ["name" : "saved" as NSSecureCoding]
                }
        
        UIApplication.shared.shortcutItems = [
            UIApplicationShortcutItem(type: "Tweet", localizedTitle: "Tweet", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .compose), userInfo: tweetuserInfo),
            UIApplicationShortcutItem(type: "Call", localizedTitle: "Call", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .audio), userInfo: calluserInfo),
            UIApplicationShortcutItem(type: "Message", localizedTitle: "Message", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .message), userInfo: messageuserInfo),
            UIApplicationShortcutItem(type: "Saved", localizedTitle: "Saved", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .love), userInfo: saveduserInfo),
        ]
    }
    
    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
            if let shortcutItem = options.shortcutItem {
                shortcutItemToHandle = shortcutItem
            }
            
            let sceneConfiguration = UISceneConfiguration(name: "Custom Configuration", sessionRole: connectingSceneSession.role)
            sceneConfiguration.delegateClass = CustomSceneDelegate.self
            
            return sceneConfiguration
        }
    }

    class CustomSceneDelegate: UIResponder, UIWindowSceneDelegate {
        func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
            shortcutItemToHandle = shortcutItem
        }
    }
}</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>If we test our code on our home screen we should be able to long press our icon and if we tap one of the dynamic quick action buttons it will open our app and navigate to that specific section of our app.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>That is all you need to make home screen quick action shortcuts in SwiftUI. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>All the code can be found here on my <a href="https://github.com/Tprezioso/QuickActionSwiftUIBlog">Github</a>. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I hope this helped you add quick actions to your next SwiftUI project.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Happy Coding! </p>
<!-- /wp:paragraph -->