How to get the previous viewcontroller that pushed my current view
Solution 1
If the reason for needing access to the previous view controller is to know what data to get, I would suggest that you instead give the new view controller the data before you push it on the stack. Or at least enough data so that the view controller know how to get the right data, e.g. a enum or constant or something.
This could be done with a custom initializer, or a property. Take a look at this blog post for an example: "Passing Data Between View Controllers"
If you are using a storyboard, you can use prepareForSegue:sender
to pass the right data. A good tutorial on that can be found here: Beginning Storyboards in iOS 5 Part 2
Solution 2
In Swift 3,
if let navController = self.navigationController, navController.viewControllers.count >= 2 {
let viewController = navController.viewControllers[navController.viewControllers.count - 2]
}
Solution 3
You can get the previous viewController like following code,
NSLog(@"%@",[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-2]);
This will displays the previous viewController name...
Solution 4
In Swift:
let n: Int! = self.navigationController?.viewControllers?.count
let myUIViewController = self.navigationController?.viewControllers[n-2] as! UIViewController
Solution 5
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.
Midas
Updated on July 13, 2021Comments
-
Midas almost 3 years
The home page of my app has
UIButtons
,btnIncome
andbtnExpense
. Pressing on this buttons pushesIncomeVC
andExpenseVC
respectevely,which are twoUIViewControllers
withUITabBar
added via xib. The tabBar have 4 items. Selecting on each tab item adds same four view controllers(which containsUITableViews
) as the subview ofIncomeVC
andExpenseVC
,like for eg, DailyVC,WeeklyVC,MonthlyVC,YearlyVC.(ie,for Income ,there is daily,weekly etc and same for Expense) (I have done like that because theIncomeVC
andExpenseVC
have aUIButton
and aUIView
which is common for all tabs).So the problem is that, if click the
btnIncome
I have to populate those tableviews with the arrays related to Income and vice versa for Expense. How can I find from which viewController I selected the different tabs(I need to get it from the 4 Views I added as the subview of IncomeVC and ExpenseVC). Do I have to make 8 different views 4 each for Income and expense ? Thanx. -
Cyprian over 10 years@Erik count property is always greater by 1 then the index so to get the UIViewController before the current UIViewController you must subtract 2 from the count
-
baquiax almost 8 yearsIt's unsafe access directly n-2 because if you are the first VC you will have an error. Maybe you can use an previous validation.
-
J.beenie about 7 yearsIs it possible to have a situation in which the view controller being viewed is not on the top of the navigation stack?
-
RubenVot over 6 yearsPotential crash due to array out of bounds
-
RubenVot over 6 yearsI obviously know and that's the reason why I downvoted. You should fix your code or add the comment warning other people that your code is insecure. btw, I upvoted you answer for Swift 3