The home page of my app has UIButtons
, btnIncome
and btnExpense
. Pressing on this buttons pushes IncomeVC
and Expen
extension UINavigationController {
func getPreviousViewController() -> UIViewController? {
let count = viewControllers.count
guard count > 1 else { return nil }
return viewControllers[count - 2]
}
}
In Swift:
let n: Int! = self.navigationController?.viewControllers?.count
let myUIViewController = self.navigationController?.viewControllers[n-2] as! UIViewController
Swift 3
Here is a mashup of the previous answers that can be put into an extension:
extension UIViewController{
var previousViewController:UIViewController?{
if let controllersOnNavStack = self.navigationController?.viewControllers, controllersOnNavStack.count >= 2 {
let n = controllersOnNavStack.count
return controllersOnNavStack[n - 2]
}
return nil
}
}
Edit:
When fetching the previousViewController
of a given view controller, call it VC1, in viewWillDisappear
, VC1 is already popped of the Navigation Controller Stack. So in this scenario, the above code does not end up fetching the View controller directly above VC1(call it VC2), but the view controller above VC2 (if it exists).
To avoid this problem I just check if VC1 is still on the stack when previousViewController
is requested. Here is the updated code:
extension UIViewController{
var previousViewController:UIViewController?{
if let controllersOnNavStack = self.navigationController?.viewControllers{
let n = controllersOnNavStack.count
//if self is still on Navigation stack
if controllersOnNavStack.last === self, n > 1{
return controllersOnNavStack[n - 2]
}else if n > 0{
return controllersOnNavStack[n - 1]
}
}
return nil
}
}
This code assumes that view controller you are sending the previousViewController
message to will either be at the top of the navigation stack or not at all.
In Swift 3,
if let navController = self.navigationController, navController.viewControllers.count >= 2 {
let viewController = navController.viewControllers[navController.viewControllers.count - 2]
}