Using home screen quick actions with SwiftUI Lifecycle

I am currently in the middle of updating an UIKit app over to using the new SwiftUI lifecycle and can't get home screen quick actions to work. (I have just static quick actions in the app)

I have tried to inject the old app delegate into the new App like this:
Code Block Swift
import SwiftUI
@main
struct MainApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}


With the AppDelegate looking like this:
Code Block Swift
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if let shortcutItem = launchOptions?[UIApplication.LaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {
            handleShortcut(shortcutItem: shortcutItem)
            return false
       
        }
        return true
}
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        let handledShortCutItem = handleShortcut(shortcutItem: shortcutItem)
        completionHandler(handledShortCutItem)
    }
func handleShortcut(shortcutItem: UIApplicationShortcutItem) -> Bool {
///Code to handle shortcut
}
}


When i run the app, I can see the didFinishLaunchingWithOptions is getting called, but when i trigger a home screen quick action, the performActionFor func is not called.

My info.plist is setup currently and they work if I switch back to UIKit


Am I missing something here?







Answered by emcro in 628604022
Hi, I filed a Feedback and got an answer which pointed me in the right direction.

In your UIApplicationDelegateAdaptor, override the configurationForConnecting function and set up a custom scene configuration and set its delegateClass accordingly:

Code Block
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    let sceneConfiguration = UISceneConfiguration(name: "Custom Configuration", sessionRole: connectingSceneSession.role)
    sceneConfiguration.delegateClass = CustomSceneDelegate.self
     
    return sceneConfiguration
  }


Then create a custom scene delegate which can handle the shortcutItem as we used to do with the old Scene Delegate methods (and this works with any scene delegate method of course):

Code Block
class CustomSceneDelegate: UIResponder, UIWindowSceneDelegate {
  @Environment(\.openURL) var openURL
   
  func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
    handleShortcutItem(shortcutItem)
  }
   
  func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) {
    if shortcutItem.type == "Offers" {
      print("Quick launch to Offers")
       
      if let url = URL(string:"cardpointers://open/offer/0") {
        openURL(url)
      }
    }
...
}
}


Hope this helps! I've not been able to find anyone who knew how to do this until Apple replied to the Feedback (and they did so in just one day) so I highly recommend more folks use that system, it can be a real godsend.

Cheers!
Accepted Answer
Hi, I filed a Feedback and got an answer which pointed me in the right direction.

In your UIApplicationDelegateAdaptor, override the configurationForConnecting function and set up a custom scene configuration and set its delegateClass accordingly:

Code Block
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    let sceneConfiguration = UISceneConfiguration(name: "Custom Configuration", sessionRole: connectingSceneSession.role)
    sceneConfiguration.delegateClass = CustomSceneDelegate.self
     
    return sceneConfiguration
  }


Then create a custom scene delegate which can handle the shortcutItem as we used to do with the old Scene Delegate methods (and this works with any scene delegate method of course):

Code Block
class CustomSceneDelegate: UIResponder, UIWindowSceneDelegate {
  @Environment(\.openURL) var openURL
   
  func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
    handleShortcutItem(shortcutItem)
  }
   
  func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) {
    if shortcutItem.type == "Offers" {
      print("Quick launch to Offers")
       
      if let url = URL(string:"cardpointers://open/offer/0") {
        openURL(url)
      }
    }
...
}
}


Hope this helps! I've not been able to find anyone who knew how to do this until Apple replied to the Feedback (and they did so in just one day) so I highly recommend more folks use that system, it can be a real godsend.

Cheers!
Using home screen quick actions with SwiftUI Lifecycle
 
 
Q