简体   繁体   中英

Dismiss any loaded view in a navigation stack and return to the root of navigation stack

Tab1 -> Nav1 -> Root1VC -> Child1VC

Tab2 -> Nav2 -> Root2VC -> Child2VC

In Root1VC I show different content based on user's login status.

Lets's say I've visited Child1VC then tapped on Tab2, on Tab2 I tap on login. At this point I want to dismiss any presented views in Nav1 stack and return to root of Nav1 and call a func in Root1VC. How to do it?

I've following code, which works but I'm not sure if this is the best approach.

let appDelegate = UIApplication.shared.delegate as! AppDelegate

if let tabBar:UITabBarController = appDelegate.window?.rootViewController as? UITabBarController {
    
    if let menuNav:UINavigationController = tabBar.viewControllers?[2] as? UINavigationController {
        var topPresentedVC: UIViewController!
        
        if let topVC = menuNav.topViewController {
            topPresentedVC = topVC
            
        } else if let presentedVC = menuNav.presentedViewController {
            topPresentedVC = presentedVC
        }
        
        if topPresentedVC != nil {
            if !topPresentedVC.isKind(of: MoreViewController.classForCoder()) {
                topPresentedVC.navigationController?.popToRootViewController(animated: false)
            }
            
            if let moreVC = menuNav.viewControllers.first as? MoreViewController {
                moreVC.initMenus()
            } else {
                print("Can't find first VC")
            }
        }
    }
}

Function below returns 'false' in case when something was not as expected and 'true' if everything went as expected. If you would like to have more details about which expectation was not meat then you have to transform the function into throwing one and instead returning false you must create a detailed error.

The function can be placed as global function or be part of a type.

func popToRootViewControllerOfSecondTabOnLogOut() -> Bool {
    guard let window = UIApplication.shared.keyWindow else {
        return false
    }
    guard let tabBarController = window.rootViewController as? UITabBarController else {
        return false
    }
    guard tabBarController.viewControllers?.indices.contains(2) == .some(true) else {
        return false
    }
    guard let navigationController = tabBarController.viewControllers?[2] as? UINavigationController else {
        return false
    }
    
    navigationController.popToRootViewController(animated: true)
    
    guard let moreViewController = navigationController.viewControllers.first as? MoreViewController else {
        return false
    }
    
    moreViewController.initMenus()
    
    return true
}

Short version of above logic without a feedback if the logic was executed as expected

let nvc = ((UIApplication.shared.keyWindow?.rootViewController as? UITabBarController)?.viewControllers?[2] as? UINavigationController)
        nvc?.popToRootViewController(animated: true)
(nvc?.viewControllers.first as? MoreViewController)?.initMenus()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM