I have a firstViewController embedded in a firstNavigationController that has a modal segue to a new secondViewController embedded in another secondNavigationController. This new controller performs an unwind segue back to the firstViewController
secondViewController:
- (void) cancelAction{
[self performSegueWithIdentifier:#"backHoney" sender:self];
}
firstViewController:
- (IBAction)backToHoney:(UIStoryboardSegue *)sender{
}
This works but there is a case when another viewC embedded in a Nav has a modal segue to the firstViewController. When the user goes from this viewC to the firstViewController then to the secondViewController and tries to unwind back to the first, it unwinds all the way back to viewC instead of the first.
you should use popToviewController instead of unwing segue. you can go to any viewController of navigation stack by this.
for example,
NSArray *viewArr = [self.navigationController viewControllers]; //returs viewcontroller array
[self.navigationController popToViewController:[viewArr objectAtIndex:0] animated:YES];
//you can pass different index to go to differen VC
You can refer my this answer for more detail.
hope this will help :)
Related
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
I've a navigationController. The first viewcontroller is a kind of class FirstViewController. When I tap a button in FirstViewController, it push in navigationController the second viewController that is a kind of class SecondViewController. When I tap a button in SecondViewController, I'd like to dealloc the FirstViewController (previously saved in navigationController) so as to start again as if it was the first time that I open the FirstViewController when I tap back button in navigationItem of SecondViewController. Here the code of the method called when I tap the button in secondViewController:
NSArray * navigationPath = [self.navigationController viewControllers];
UIViewController *previousVC = [navigationPath objectAtIndex:[navigationPath count]-2];
[previousVC performSelector:#selector(viewDidUnload)];
It doesn't dealloc the FirstViewController. There is a way to do it?
Create a new first view controller
FirstViewController *first = [[FirstViewController alloc]init];
Reset the navigation stack
[self.navigationController setViewControllers:#[first, self] animated:NO];
Navigate to first
[self.navigationController popViewController:YES];
You will need to reset the array of view controllers in the navigation controller.
In your second view controller:
[self.navigationController setViewControllers:#[self] animated:NO];
I have 3 navigation controllers. Each with many view controllers.
1 NavigationController (modal Segue)-> 2 NavigationController (model Segue)-> 3 NavigationController
Now, how do you go from #3 NavigationController back to #1 NavigationController that I have been before? So I want
1 NavigationController (modal Segue)-> 2 NavigationController (model Segue)-> 3 NavigationController (HOW???)-> 1 NavigationController
(To clarify, I would not want to go to a new 1 NavigationController. I want to go to the one that I used before.)
Help!
[[self navigationController] popViewControllerAnimated:YES];
If you just want to dismiss the whole stack of 3 NavigationController, you can call this within any view controller in the 3
Objective C
[self.navigationController dismissViewControllerAnimated:YES completion:nil]
Swift 3, 4
self.navigationController?.dismiss(animated: true)
This will bring you back to the status before (model Segue)-> 3 NavigationController.
Maybe you can somehow call this in 2 before calling this in 3?
Use that:
[self.**presentingViewController** dismissViewControllerAnimated:YES completion:nil];
instead of:
[self dismissViewControllerAnimated:YES completion:nil];
In a view controller in navigationController1's stack, create an unwind #IBAction method:
Swift
#IBAction func unwindToMyViewController(_ segue: UIStoryboardSegue)
Objective-C
- (IBAction)unwindToMyViewController:(UIStoryboardSegue *)segue
In your storyboard, you can then hook up an unwind segue from a button in a view controller that is in the stack of navigationController3, by dragging from the button to the exit icon…
from there, select the unwind segue created above. When triggered, the segue will unwind ALL view controllers back to the view controller containing the unwind segue.
With help of this, You can get the 1 Nav controll :-
[(UINavigationController *)self.view.window.rootViewController popViewControllerAnimated:YES];
this code will pop a navigation controller with all view controllers in it
// pop root view controller
UIViewController *rootViewController = [self.navigationController viewControllers][0];
[rootViewController dismissViewControllerAnimated:YES completion:nil];
so you can do something like this:
// pop navigationController3 without animation
UIViewController *rootViewController3 = [navigationController3 viewControllers][0];
[rootViewController3 dismissViewControllerAnimated:NO completion:nil];
// pop navigationController2 with animation
UIViewController *rootViewController2 = [navigationController2 viewControllers][0];
[rootViewController2 dismissViewControllerAnimated:YES completion:nil];
From Home view - my RootViewController - I open up 2 ViewControllers one after another as user progresses in navigation hierarchy like so:
1) SecondViewController is pushed by button connected in my Storyboard
2) ThirdViewController is presented modally
[self performSegueWithIdentifier:#"NextViewController" sender:nil];
So, the picture is: RootViewController -> SecondViewController -> ThirdViewController
Now in my ThirdViewController I want to have a button to go back 2 times to my RootViewController, i.e. go home. But this does not work:
[self.navigationController popToRootViewControllerAnimated:YES];
Only this guy goes back once to SecondViewController
[self.navigationController popViewControllerAnimated:YES];
How can I remove both modal and pushed view controllers at the same time?
I had a similar situation, where I had a number of view controllers pushed onto the navigation controller stack, and then the last view was presented modally. On the modal screen, I have a Cancel button that goes back to the root view controller.
In the modal view controller, I have an action that is triggered when the Cancel button is tapped:
- (IBAction)cancel:(id)sender
{
[self.delegate modalViewControllerDidCancel];
}
In the header of this modal view controller, I declare a protocol:
#protocol ModalViewControllerDelegate
- (void)modalViewControllerDidCancel;
#end
And then the last view controller in the navigation stack (the one that presented the modal view) should implement the ModalViewControllerDelegate protocol:
- (void)modalViewControllerDidCancel
{
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popToRootViewControllerAnimated:YES];
}
This method above is the important part. It gets the presenting view controller to dismiss the modal view, and then it pops back to the root view controller. Note that I pass NO to dismissViewControllerAnimated: and YES to popToRootViewControllerAnimated: to get a smoother animation from modal view to root view.
I had the same requirement but was using custom segues between the view controllers. I came across with the concept of "Unwind Segue" which I think came with iOS6. If you are targeting iOS6 and above these links might help:
What are Unwind segues for and how do you use them?
http://chrisrisner.com/Unwinding-with-iOS-and-Storyboards
Thanks.
Assuming your AppDelegate is called AppDelegate, then you can do the following which will reset the rootviewcontroller for the app window as the view RootViewController
AppDelegate *appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate];
RootViewController *rootView = [[RootViewController alloc] init];
[appDel.window setRootViewController:rootView];
I have hierarchy of ViewControllers in my storyboard structure.
It is A-B-C-D. A is embed with NavigationController and the flow goes on till D viewController. All fours view attached through segues. Now I am on D viewController, I defined some action to the button of D that It should take me directly to A viewController that is rootViewController or B viewController. Then how can I achieve this. I tried everything but didn't succeed.
I want something like it should not disturb A-B-C-D flow and it should take me to A viewController from D.
Right click on your D viewcontroller and drag i to your A viewcontroller.
Then click on the object which appears on the line you just created.
Write something like DtoA in the storyboard segue identifier in the attributes inspector.
Now in D view controller, just do:
[self performSegueWithIdentifier:#"DtoA" sender:self];
And if you instead wish to pop to a previous viewcontroller the old fashioned way, like from D to B:
UINavigationController* navController = self.navigationController;
UIViewController* Bviewcontroller = [navController.viewControllers objectAtIndex:1];
[navController popToViewController:controller animated:YES];
I hope this helps!