Currently I'm using Unwind to get to the Main View of its Path.
This is the code I've on the Sender ViewController:
- (IBAction)showRecents:(UIStoryboardSegue *)segue {
[self.navigationController.tabBarController setSelectedIndex:1];
NSLog(#"Root of Navigation Executed");
}
This is how it looks before unwinding
And this is how it looks after unwinding from the source view controller:
The issue is that I don't understand why it's not showing the Green TopBar? Has something to do with the TabBarController?
This is my Path VC:
The answer to this Question is to. First we need to Hide/Show the NavigationController on the Source ViewController and Before it disappear We need to Show it again. That Way on the Sender ViewController You will be able to see the Navigation Because it was set to be shown on the Source where the unwind its performed.
-(void)viewWillAppear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:YES];
}
-(void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO];
}
Related
I have a Tabbarcontroller filled with 5 Viewcontrollers and Navigationcontrollers as I did here:
[self addChildViewController:VC1];
[self addChildViewController:NavigationController;
[self addChildViewController:VC2];
[self addChildViewController:VC3];
[self addChildViewController:VC4];
Now the thing is, that pressing a button on my Tabbar gets me to every ViewController easily, where I can present Xib-Files etc.
But now I want to have a Navigationcontroller, which is shown when pressing a button on my Tabbar. This Navigationcontroller itself has several Viewcontrollers.
I tried this to present my first Viewcontroller inside my Navigationcontroller (this code is from the Navigationcontroller.m):
- (void)viewDidLoad {
[super viewDidLoad];
[self addChildViewController:VC5];
[self presentViewController:VC5];
}
This expectedly did not work and gave me: Application tried to present modally an active controller.
Is there a good way to achieve such a specific goal? I'm struggling with this problem. Thanks in advance!
edit: This is how I set it up in my storyboard. In my programmatic approach the first view controller is not shown.
Instead of adding the VC5 view controller to the NavigationController as a child (unless it's meant to be a child?) add it as the root view controller when you add the NavigationController to the tab bar.
For example in your tab bar code:
[self addChildViewController:VC1];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:VC5];
[self addChildViewController:navigationController];
[self addChildViewController:VC2];
[self addChildViewController:VC3];
[self addChildViewController:VC4];
Apple docs on UINavigationController are here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/#//apple_ref/occ/instm/UINavigationController/initWithRootViewController:
I am trying to navigate to "Home" view controller and for this I have written the following code in the ContainerViewController. But once the code executes, the application hangs and it show 100% CPU usage. Please help.
- (IBAction) home:(UIButton *)sender
{
HomeViewController *homeViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
[self.navigationController pushViewController:homeViewController animated:YES];
//[self presentViewController:homeViewController animated:YES completion:nil];
}
I have a question for you
1-If You want to push SecondViewController on to FirstViewController then your code is good enough
2-If you have a containerview in firstViewController and you want to add SecondViewcontroller's view to firstViewController
then use this code
UIViewController*vc1 = [[test1 alloc]initWithNibName:#"SecondViewController" bundle:nil];
//add to the container vc which is self
[self addChildViewController:vc1];
//the entry view (will be removed from it superview later by the api)
[self.view addSubview:vc1.view];
I think you want an unwind segue here. In your first view controller add :
- (IBAction)unwindToFirstViewController:(UIStoryboardSegue*)sender
{
}
You then need to hook up each of your view controllers home button to the green Exit button at the bottom of the view controller, choosing the unwindToMainMenu option. This will then take you back to the first view controller when pressed.
Have you tried popping the current view?
navigationController?.popViewControllerAnimated(true)
or just popping to root?
navigationController?.popToRootViewControllerAnimated(true)
or setting a new stack?
navigationController?.setViewControllers(homeViewController, animated: true)
The code is in Swift but it would work the same in ObjectiveC
So I was create three UITableViewControllers with UINavigationController. I want a back button on 3rd UITableViewController, what returns my view to first UITableViewController instead of second.
How can I do that? That must be a real backButton, not a image or something else. Will be perfect to do this only with storyboard.
UPDATE
Perhaps I poorly explained what I want.
I don't want use any button with action on it. I just want something like as setting "address" of 1st TableViewController on my default back button. There is any way to do it?
add a button and connect it to following action
- (IBAction)backToFirstView:(UIButton *)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
(or)
[self.navigationController popToViewController:yourFirstViewControllerObject animated:YES];
}
There are different ways to navigate from DetailViewController to other view controllers.
We will go through the cases one by one.
First of all I would like to clear that if its your default
navigation bar's back button, then it must return to the last most
view controller only which is actually a default behavior of a
navigation controller.
Second, If you would like to go back to the
last most view controller on the tap of a button placed by you, you
should write the following code
[self.navigationController popToViewController:NAME_OF_A_VIEWCONTROLLER animated:YES];
Third, If you would like to go to the first view controller from where you
started, you should write the following code
[self.navigationController popToRootViewControllerAnimated:YES];
Ok, I found a way to resolve my problem. Thanks for your answers guys, they was very helpful.
So for resolve this problem you just need use link what give me Kumar KL upper, and wrote next method in your UITableVIewController
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// Navigation button was pressed. Do some stuff
[self.navigationController popViewControllerAnimated:NO];
}
[super viewWillDisappear:animated];
}
Now you got a backButton what redirect you to your viewController, BUT title of this button is wrong. Let's resolve that unfair.
Create new class CustomSegueцрфе inherited from UIStoryboardSegue with next code in CustomSegue.m :
- (void)perform
{
UIViewController *sourceView = (UIViewController *) self.sourceViewController;
UIViewController *destinationView = (UIViewController *) self.destinationViewController;
[[destinationView navigationItem] setTitle:#"TitleOfYourViewController" ] ;
[sourceView.navigationItem setTitle:#"TitleOfButton"] ;
[sourceView.navigationController pushViewController:destinationView animated:YES];
}
Now you can go to storyboard and connect 2nd ViewController with 3rd with custom segue.
Like you see UINavigationController uses Title of previous ViewController for button title, so you just need change it.
I have an UITabBarController that has 3 buttons. The second button points to ViewController1 which is connected to another view called ViewController2. After I tap a button in ViewController2 I programmatically present ViewController1 again, that works perfect except one thing. After I "arrived" to ViewController1 the tab bar disappears.
I'm using this method to navigate back to ViewController1. (exactly I navigate to its navigation controller, but already tried with the view)
- (void)presentViewControllerAnimated:(BOOL)animated {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyboard" bundle:nil];
UINavigationController *firstViewNavigationController = [storyboard instantiateViewControllerWithIdentifier:#"destination"];
[self presentViewController:firstViewNavigationController animated:animated completion:nil];
}
I call here the first method
- (void)didTapButton:(id)sender {
UIButton *button = (UIButton *)sender;
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
[self presentViewControllerAnimated:YES];
}
This method hides the tab bar in the ViewController2, I already tried without it, therefore there is no problem with it.
-(BOOL)hidesBottomBarWhenPushed
{
return YES;
}
I can't figure out why this thing happens, I think it's a fair solution, that worked well for a several times when I needed to present views. I've read it can happen with segues, but I'm doing it with code without segues.
Actually your code works right. There should not be tab bar when you present FirstViewController from SecondViewController. Because when you call instantiateViewControllerWithIdentifier its basically creates a new instance of that view controller, and of course, there is no tab bar.
The right way to go back to your first view controller is to pop SecondViewController (or dismiss it, if it presented modally). So your final code should be like this
- (void)didTapButton:(id)sender {
// If this view controller (i.e. SecondViewController) was pushed, like in your case, then
[self.navigationController popViewControllerAnimated:YES];
// If this view controller was presented modally, then
// [self dismissViewControllerAnimated:YES completion:nil];
}
And of course, your view controller hierarchy in storyboard must be like this:
-- UINavigationController -> FirstViewController -> SecondViewController
|
->UITabBarController____|
-...
-...
I've tried the same and got the same result.
My solution was simple, on the push do this :
UINavigationController *firstViewNavigationController = [storyboard instantiateViewControllerWithIdentifier:#"destination"];
firstViewNavigationController.hidesBottomBarWhenPushed = true; // Insert this and set it to what you want to do
[self presentViewController:firstViewNavigationController animated:animated completion:nil];
and then remove your
-(BOOL)hidesBottomBarWhenPushed
{
return YES;
}
I'm using IOS5 Storyboard. My View Controller path is as follows:
tabbarVC --> navigationVC-1 --> tableVC-1 --(via segue push)-> tableVC-2 --(via segue modal)-> navigationVC-2 --> tableVC-3
In the cancel button callback action method in tableVC-3 I call [self dismissViewControllerAnimated:YES completion:nil]; that successfully gets me back to tableVC-2. However when I try to examine the navigation path backwards in the debugger, I don't see a way to access tableVC-2 from navigationVC-2. I expected navigationVC-2 to maintain a link to tableVC-2 or navigationVC-1 but it doesn't seem to. Please see my debugger output below.
Can someone explain the navigation hierarchy and how to traverse the chain backwards programatically?
(gdb) po self
<tableVC-3: 0x6d33340>
(gdb) po (UIViewController*) [self navigationController]
<UINavigationController: 0x6d33560>
(gdb) po (UIViewController*)[[self navigationController] navigationController]
Can't print the description of a NIL object.
(gdb) po (UIViewController*)[[self navigationController] topViewController]
<tableVC-3: 0x6d33340>
(gdb) po (UIViewController*)[[self navigationController] presentingViewController]
<UITabBarController: 0x6b2eba0>
(gdb) po (UIViewController*)[[self navigationController] presentedViewController]
Can't print the description of a NIL object.
(gdb) po (UIViewController*)[[self navigationController] visibleViewController]
<tableVC-3: 0x6d33340>
This is an old question, but just to help anyone else who comes across this issue, there's a single command which'll make your life easier..
[self.navigationController popToRootViewControllerAnimated:TRUE];
Easy when you stumble across the right command, isn't it !
So, supposing you had a series of three screens in a Navigation Controller, and on the third screen you wanted the "Back" button to take you back to the initial screen.
-(void)viewDidLoad
{
[super viewDidLoad];
// change the back button and add an event handler
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack:)];
}
-(void)handleBack:(id)sender
{
NSLog(#"About to go back to the first screen..");
[self.navigationController popToRootViewControllerAnimated:TRUE];
}
After some research using this and a couple other questions for modal UIViewControllers in storyboard to go back two views I used
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Going throw an old response tough of updating it to be more complet.
To address this question :
Can someone explain the navigation hierarchy and how to traverse the chain backwards programatically?
The structure of your navigation :
tabbarVC --> navigationVC-1 --> tableVC-1 --(via segue push)-> tableVC-2 --(via segue modal)-> navigationVC-2 --> tableVC-3
Can be explain like this :
The TabbarVC is showing it's 'selectedViewController' (navigationVC-1).
NavigationVC-1 has its navigation stack compose of TableVC-1 and TableVC-2 (topViewController of NavigagtionVC-1)
Then NavigationVC-2 is presented Modally over the tabbarVC, so tabbarVC is the presentingViewController and NavigationVC-2 is the presentedViewController
So in order to reach tableVC-2 from tableVC-3 you would need to do something like this :
[(UINavigationController *)[(UITabBarController *)[tableVC-3 presentingViewController] selectedViewController] topViewController];
(don't do that in production code)
[tableVC-3 presentingViewController] as well as [tableVC-3.navigationController presentingViewController] will give you back the UITabBarController.
If you are using a UINavigationController you should use it's push and pop method to put UIViewController on or off the "presentation stack".
You will be able to access the UINavigationController from those UIViewController like this:
self.navigationController
If you want to go back more than one UIViewController on the "presentation stack" you can use this method on the UINavigationController
popToViewController:animated:
Pops view controllers until the specified view controller is at the top of the navigation stack.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
To dismiss a UIViewController that was presented modally, the UIViewController that have presented it need to dismiss it with :
- (void)dismissModalViewControllerAnimated:(BOOL)animated
So in this case it should be :
[tableVC-2 dismissModalViewControllerAnimated:YES];
Swift
If you are using a navigation controller the you can navigate back to the previous view controller with
self.navigationController?.popViewControllerAnimated(true)
or back to the root view controller with
self.navigationController?.popToRootViewControllerAnimated(true)