perage
perage

Reputation: 143

How to get to the deepest viewController in a complex hierarchy

I have a Hierarchy looking like this:

VC Hierarchy

  1. UITabBarController

1.1 ViewController with 2 containerViews

1.1.1. UINavigationController

1.1.1.1. UITableViewController

1.1.1.1.1 UITableViewController

1.2 ViewController with 2 containerViews

1.2.1. UINavigationController

1.2.1.1. UITableViewController

1.2.1.1.1 UITableViewController

Wanted solution

I want to have the deepest VC PopToRoot when the tabBar is choosen.This post explains how

I've managed to find the correct VC in debugger, but when writing code to get it, Xcode complains with Segmentation Fault 11

Code

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController ) -> Bool {

if tabBarController.selectedViewController === viewController {

if let nc = viewController.children.first(where: { $0.isKind(of: UINavigationController.self)}) as? UINavigationController {

if let handler = nc.children.first(where: { $0.isKind(of: TabBarReselectHandling.self )}) as? TabBarReselectHandling {
handler.handleReselect()
            }
        return true
    }

As soon as I comment out the if let handler line, Xcode shows error: An internal error occured. Source editor functionality is limited. Attempting to restore...

This line works for one tabBarItem, but not all, as the two containerViews in VC 1.1 & 1.2 might be in different order

let handler = viewController.children[1].children[1] as? TabBarReselectHandling

Any suggestions on how I can get safely to my deepest VC?

Upvotes: 0

Views: 216

Answers (2)

Sreeraj VR
Sreeraj VR

Reputation: 1574

Try this Swift 4 version

        if (navigationController?.viewControllers.filter { $0 is YourFirstViewController }.first != nil)

        {
            let dashboardVC = navigationController!.viewControllers.filter { $0 is YourFirstViewController }.first
            navigationController!.popToViewController(dashboardVC!, animated: true)
        }
            
        else if (navigationController?.viewControllers.filter { $0 is YourSecondViewController }.first != nil)
        {
            let dashboardVC = navigationController!.viewControllers.filter { $0 is YourSecondViewController }.first
            navigationController!.popToViewController(dashboardVC!, animated: true)
        }

Upvotes: 0

Frankenstein
Frankenstein

Reputation: 16341

You could check for the selectedIndex and cast the viewController as UINavigationController and then perform popToRootViewController(animated:) on it to achieve this result.

func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
    if selectedIndex == 0, let navVC = viewController as? UINavigationController { // replace 0 with your value
        navVC.popToRootViewController(animated: true)
    }
}

Note: For this to work, your implementation of func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController ) -> Bool method should be removed.

Upvotes: 1

Related Questions