Search code examples
iosswiftuinavigationcontroller

How to remove navigation bar items when a view controller is removed from navigation stack?


I am removing login view controller from navigation stack once user gets logged in. However, the navigation bar button items added by the login view controller still remains. How to completely remove a view controller from navigation stack?

static func removePreviousFromNavigationStack(_ navVC: UINavigationController) {
    var navArr = navVC.viewControllers
    for elem in navArr {
        if elem.isKind(of: LoginViewController.self) {
            if let vc = StateData.loginVC {
                vc.navigationItem.leftBarButtonItem = nil  // is not working as intended
                vc.navigationItem.rightBarButtonItem = nil
                vc.navigationItem.title = "Foo"
            }
            //elem.removeFromParent()
        }
    }
    navArr.remove(at: navArr.count - 2)
    navVC.viewControllers = navArr
}

Flow: HomeVC -> ApplyVC -> LoginVC -> FormVC

After logging in to FormVC, I call the remove method to remove LoginVC from the stack. This removes the VC, but the nav buttons remains. If I set the nav button to nil, the ApplyVC's leftButtonItem, back button, right button item, home button does not show. There is a transparent back button which when clicked, displays the nav bar buttons of ApplyVC as if the LoginVC got popped out of the view, but without any changes to the current view.

screens


Solution

  • Try removing the LoginVC at the time of pushing FormVC instead of after the FormVC is visible.

    I’ve created the same NavigationStack as yours.

    1. Added a rightBarButton in HomeVC

    class HomeVC: UIViewController {
        var rightBarItem: UIBarButtonItem = {
            return UIBarButtonItem(barButtonSystemItem: .bookmarks, target: nil, action: nil)
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "HomeVC"
            self.navigationItem.rightBarButtonItem = rightBarItem
        }
    }
    
    class ApplyVC: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "ApplyVC"
        }
    }
    

    2. Added a rightBarItem in LoginVC

    class LoginVC: UIViewController {
        var rightBarItem: UIBarButtonItem = {
            return UIBarButtonItem(barButtonSystemItem: .add, target: nil, action: nil)
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "LoginVC"
            self.navigationItem.rightBarButtonItem = rightBarItem
        }
    
        @IBAction func onTapButton(_ sender: UIButton) {
            var controllers = self.navigationController?.viewControllers
            let formVC = self.storyboard?.instantiateViewController(withIdentifier: "FormVC") as! FormVC
            controllers?.removeAll(where: { $0 is LoginVC })
            controllers?.append(formVC)
            if let controllers = controllers {
                self.navigationController?.setViewControllers(controllers, animated: true)
            }
        }
    }
    

    In the above code, I’ve filtered the LoginVC and added FormVC from navigationController’s viewControllers array.

    class FormVC: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "FormVC"
        }
    }
    

    enter image description here