Search code examples
iosswiftuiapplicationshortcutitem

Application Shortcut Open TableView Row


I have four application shortcuts set up when force pressing my app icon. I have a tab bar controller with navigation controllers each with table view controllers as the root view controller for the first two tabs.

For the shortcuts, how can I open either the first or second tab and select a row from the corresponding table view?

I think I would start with this but please correct me if I'm wrong.

let tabNav:UINavigationController = tabBar.viewControllers?[0] as! UINavigationController

---EDIT--- After working with the answer provided, I have this somewhat working.

let navigationController = tabBar.viewControllers![0] as! UINavigationController
let tableViewController = navigationController.viewControllers.first as! FederationTableViewController
let indexPath = IndexPath(row: 0, section: 0)
tableViewController.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .top)
tableViewController.tableView.delegate?.tableView!((tableViewController.tableView)!, didSelectRowAt: indexPath)

tabBar.selectedIndex = 0

This selects the correct row and opens the correct view controller. The issue I'm having with it now is that it is pushing the view controller for the selected row twice so the view controller that is pushed when selecting that row is being loaded twice.


Solution

  • You need to receive the shortcut item in app delegate, then take appropriate action based on the type of shortcut that you will have defined in info.plist. Something like this should work, though it may need amending based on the exact structure of your app or your subclass names etc.

    In App Delegate:

    func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        print("Opening app from 3D touch shortcut...")
        completionHandler(handleShortcut(shortcutItem: shortcutItem))
    }
    
    // This function handles the shortcut. Any problems will return false, preventing the shortcut opening.
    private func handleShortcut(shortcutItem: UIApplicationShortcutItem) -> Bool {
        if shortcutItem.type == "firstShortcutType" {
            guard let tabBarController = self.window.rootViewController as? UITabBarController else { return false }
            guard let navigationController = tabBarController.viewcontrollers[0] as? UINavigationController else { return false }
            guard let tableViewController = navigationController.rootViewController as? UITableViewController else { return false }
    
            // Select index of tab bar controller
            tabBarController.selectedIndex = 0
    
            // TableView May not be loaded, so I wrap this in a delayed block
            DispatchQueue.main.asyncAfter(deadline: .now()+1, execute: {
                // Create index path
                let indexPath = IndexPath(row: 0, section: 0)
                self.tableViewController.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
            })
            return true
    
        } else if shortcutItem.type == "otherShortcutType" {
            // Handle ofher shortcut types
        } else {
            return false
        }
    }