I used the Objective-C
code below to pop a specific ViewController
.
for (UIViewController *controller in self.navigationController.
simple and best solution without force unwrapped is
if let vc = navigationController.viewControllers.filter({$0 is YourViewController}).first as? YourViewController {
self.navigationController.popToViewController(vc, animated: true)
}
Swift 5
To pop to the latest instance of a specific class, for example SomeViewController
:
navigationController?.popToViewController(ofClass: SomeViewController.self)
But you need to add ths UINavigationController
extension:
extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
if let vc = viewControllers.last(where: { $0.isKind(of: ofClass) }) {
popToViewController(vc, animated: animated)
}
}
}
Swift 4 / Swift 5
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: HomeViewController.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
I needed to use this, because in some cases app crashes:
if let navVC = self.navigationController {
let views = navVC.viewControllers as Array
for controller in views {
if controller.isKind(of: YourVC.self) {
navVC.popToViewController(controller, animated: true)
return
}
}
}
I prefer a generic way to do it.
I have this extension for the UINavigationController :
extension UINavigationController {
func backToViewController(vc: Any) {
// iterate to find the type of vc
for element in viewControllers as Array {
if "\(element.dynamicType).Type" == "\(vc.dynamicType)" {
self.popToViewController(element, animated: true)
break
}
}
}
}
Let's say I have a FOHomeVC class (who is a UIViewController) instantiated in the navigation stack.
So I would do this in my code:
self.navigationController?.backToViewController(FOHomeVC.self)
I have added an extension to UINavigationController
which helps you to find if that controller exist in navigation stack. If yes then it will be popped to that controller or else you pass new controller to push with pushController
param.
extension UINavigationController {
func containsViewController(ofKind kind: AnyClass) -> Bool {
return self.viewControllers.contains(where: { $0.isKind(of: kind) })
}
func popPushToVC(ofKind kind: AnyClass, pushController: UIViewController) {
if containsViewController(ofKind: kind) {
for controller in self.viewControllers {
if controller.isKind(of: kind) {
popToViewController(controller, animated: true)
break
}
}
} else {
pushViewController(pushController, animated: true)
}
}
}