Search code examples
swiftuinavigationcontrollerappdelegatexcode-storyboardtabbarcontroller

Instantiating deep View Controller with Tab bar and Navigation


I am using Xcode 11 and Swift 5.

Upon receiving an APNS notification, I need to jump to a view controller deep in my storyboard from AppDelegate. This viewController (chatVC) is behind a tabbar and a navigation controller and several other view controllers. See the image below. I know how to check the notification for tags and how to use launchOptions in AppDelegate to trigger the jump. But I am struggling with how to establish the context for that last view controller so that the user can use the back button all the way back to the tab bar controller.

deep link

I have read many SO answers, and tried many approaches but none seem to have the same embedding of a nav controller inside a tab bar controller. Here is my code in AppDelegate (after reading the tag in the notification):

        if tag == "CS" {
            // Set up a Chat View Controller.
            if let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController,
                let tabBarVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController) as? UITabBarController,
                let csVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.csViewController) as? CustomerServiceViewController,
                let helpVC = UIStoryboard(name:"Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.helpVC) as? HelpViewController
            {
                // Set the customer service document Id.
                chatVC.cs = cs
                // Make the tabBarVC the Root View Controller
                self.window?.rootViewController = tabBarVC
                self.window?.makeKeyAndVisible()
                // Select the Favorites Index.
                tabBarVC.selectedIndex = 0
                // Push the Customer Service VC on top.
                tabBarVC.show(csVC, sender: Any?.self)
                // Push the Help VC on top of Customer Service VC.
                csVC.show(helpVC, sender: Any?.self)
                // Push the the chat detail page on top.
                helpVC.show(chatVC, sender: Any?.self)
            }
        }
    }
    return true

What can I do to jump to the chatVC and set up the navigation context beneath it so the back button can be used?


Solution

  • Here is how you can do it:

    guard let tabBarVC = UIApplication.shared.windows.filter( {$0.rootViewController is UITabBarController } ).first?.rootViewController as? UITabBarController else { return }
    tabBarVC.selectedIndex = 0 //you can select another tab if needed
    guard let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController else { return }
    if let navController = tabBarVC.viewControllers?[0] as? UINavigationController {
       navController.pushViewController(chatVC, animated: true)
    }
    

    You can also pass objects from your notification to your chatVC here before pushing it, in case you need to do that.

    Hope this works for you!