My navigationcontroller becomes nil after my "[self.navigationController popToViewController: [self.navigationController.viewControllers objectAtIndex:0] animated:YES];"
this is my scene:
InsertViewController - > [self.navigationController pushViewController:choiceViewController animated:YES];
ChoiceViewController -> [self.navigationController pushViewController:choiceDetailViewController animated:YES];
ChoiceDetailViewController ->
InsertViewController *insertViewController = [self.navigationController.viewControllers objectAtIndex:0] ;
UINavigationController *secondaryNavigationCtrl = [[UINavigationController alloc] initWithRootViewController:insertViewController];
secondaryNavigationCtrl.navigationBar.barStyle = UIBarStyleBlackOpaque;
[self presentModalViewController:secondaryNavigationCtrl animated:YES];
[secondaryNavigationCtrl release];
[
When "ok" button pressed( self.navigationItem.leftBarButtonItem) in InsertView that just poped up, then it goes back to ChoiceDetailViewController and i do a
[code][self.navigationController dismissModalViewControllerAnimated:YES]; [/code]
After that i do a
[self.navigationController popToViewController: [self.navigationController.viewControllers objectAtIndex:0] animated:YES];
Which go back tot the InsertViewController, and when i do the cycle again i see my navigationcontroller is nil...
Any idea what I am doing wrong?
Thanks in advance.
I'm not sure I've understand what you are trying to do but, when you go back to ChoicheDetailViewController i think you should do a [self.navigationController popViewController:...] instead of [self.navigationController dismissModalViewControllerAnimated:YES] because ChoicheDetailViewController got pushed on the stack in a non modal way in the first place. So with your code you are actually dismissing the whole navigationController.
Not sure if this fixes your problem but I had this problem because the class that implemented the code that popped the view controller was actually getting popped. This caused my self.navigationController to be nil because it itself was getting removed. I moved the code to a class that was not getting popped and it did not get set to nil.
Before the stack looked like this, one of the ViewControllers gets popped self.navigationController is nil.
PopableViewController
functionThatCallsPopToViewController
PopableViewController
functionThatCallsPopToViewController
RootViewController
After
PopableViewController
PopableViewController
RootViewController
functionThatCallsPopToViewController
Since RootViewController is not popped self.navigationController did not get set to nil. The only tricky thing is, now you need to keep a reference to the RootViewController in your other viewControllers.
Related
Im using Navigation Controller for my ViewControllers,I set my importantViewController as something like this to be its RootView:
UINavigationController *navControl = [[UINavigationController alloc] initWithRootViewController: vc];
[self presentModalViewController: navControl animated: YES];
Then, I pushView anotherView the FrontViewController like this:
[self.navigationController pushViewController:vc animated:YES];
After a button is pressed in FrontViewController another view will be pushed ViewA but it is connected with another ViewController ViewB the same way as this AGAIN:
[self.navigationController pushViewController:vc animated:YES];
(Which I think Im doing wrong when dismissing either of them with [self.navigationController popViewControllerAnimated:YES];)
This is an illustration:
My problem is, I need to navigate between View A and View B then when I dismiss either of them it will got back to FrontViewController. Like a child of a child View. Thanks.
I think this is for dismissModalViewController, but try this,
From View B write code like this
[[self parentViewController].navigationController popViewControllerAnimated:YES];
and From View A you can write,
[self.navigationController popViewControllerAnimated:YES];
Or either you can use this,
[self.navigationController popToViewController:frontViewController animated:YES];
UPDATE
for (UIViewController *tmpController in [self.navigationController viewControllers])
{
if ([tmpController isKindOfClass:[FrontViewController class]])
{
[self.navigationController popToViewController:tmpController animated:YES];
break;
}
}
This is the best solution to achieve this.
Write this code on both of your View A or B.
Hope it works now :-)
There is one way #Prasad G indicated. But problem with this solution is you need the same object of frontViewController. You can't do this with creating a new object. For going to this way declare frontViewController object in appdelgate and while pushing it from importantVC use
appdelgate.frontViewController = // initialize
// Push it
While going back from view B
[self.navigationController popToViewController:appdelegate.frontViewController animated:YES];
Another solution is
for (UIViewController *vc in [self.navigationController viewControllers]) {
if ([vc isKindOfClass:[FrontViewController class]]) {
[self.navigationController popToViewController:vc animated:YES];
break;
}
}
Using this way you can go on any of view controller from any level of navigation stack.
Using the first solution if you have 10 view Controllers and you want to go on any of one so you have to first create object of all 10 View Controller in appdelegate.
This code may have spell issues as I just typed this here
Hope this helps :)
UPDATE
->You have impVC as your root view
-> You pushed frontVC
-> From there you Pushed VC_A
-> From there you want to push VC_B
so you are done with pushing and for coming back to VC_A you can use
[self.navigationController popViewControllerAnimated];
Now you can again come on VC_B and again pop it. For going to frontVC from VC_A you can use popViewControllerAnimated and for going to frontVC from VC_B you can use the for loop i mentioned.
Please explain if you are looking anything else. If you are still facing issue please explain.
[self.navigationController popToViewController:frontViewController animated:YES];
Try like this i think it will be helpful to you.
In FrontViewController After a button is pressed:
ViewA instance
[self.navigationController pushViewController:ViewA animated:YES]
When ViewA disissmed
[self.navigationController popViewControllerAnimated:YES];
Load ViewB in ViewA
ViewB instance
[self.navigationController pushViewController:ViewB animated:YES]
On back viewB to FrontViewController
FrontViewController instance
[self.navigationController popToViewController:FrontViewController animated:YES];
On back viewB to viewA
[self.navigationController popViewControllerAnimated:YES];
I want to go back to the first view controller. So, I used [self.navigationController popToRootViewControllerAnimated:NO] from the third view. But, it goes back to just the second view. Do I have to use popToViewController: animated: instead?
I pushed the third view like this:
[self.view addSubview:secondController.view]; // from the first view
[self.navigationController pushViewController:thirdController animated:YES]; // from the second view
Remove the second view, before using [self.navigationController popToRootViewControllerAnimated:NO]:
UIView *v = [self.navigationController.viewControllers objectAtIndex:1];
[v removeFromSuperview];
EDIT:
I am doing like this and works ok (I use this on my third view on the stack):
NSMutableArray *allControllers = [[NSMutableArray alloc] initWithArray:self.navigationController.viewControllers];
[allControllers removeObjectAtIndex:1];
[self.navigationController setViewControllers:allControllers animated:NO];
[allControllers release];
[self.navigationController popViewControllerAnimated:YES];
It looks like your navigationController was initiated when pushing the thirdController. Your secondController was not 'pushed' by the navigationController, it was added as a subview, which is quite different. So, when you push the thirdController from the secondController, it thinks your rootController is the secondController.
You have two options here:
Change the way you are presenting the secondController to actually
have the navigationController push it, or
Remove the secondController from view before the thirdController is presented.
You may be able to popToViewController, as you mentioned...I'm not positive if that will work, but it's possible.
I have a UIViewController that I wish to push onto the stack, however, when I call [viewController release] on it after I push it, any time I pop it off of the stack however, I get various errors pertaining to deallocated instances of the view controller. Here is an example of an implementation:
RootViewController *rootViewcontroller = [[RootViewController alloc] initWithNibName:#"RootViewController"
bundle:nil];
[self.navigationController pushViewController:rootViewController animated:YES];
[rootViewController release];
In the code that you showed you create rootViewController but actually push personsViewController. Typo? Or did you paste the wrong code?
Your RootViewController instance is "rootViewcontroller" but you're pushing "rootViewController" (notice the 'C'?).
So I'm trying to pop a view controller off the stack when an error occurs, but it seems like it's popping too much off in one go. The navigation bar up the top loses its title and buttons, but the old table view data remains visible. I have no idea what's going on...
The basic set up is:
Tab View template
Navigation controller
View controller (Loaded from the xib)
View controller (Pushed, what I want to pop)
Here's the code:
NSLog(#"%#", [[self navigationController] viewControllers]);
[[self navigationController] popViewControllerAnimated:NO];
NSLog(#"%#", [[self navigationController] viewControllers]);
The resulting NSLog's show:
2009-09-22 19:57:14.115 App[34707:550b] (
<MyViewController: 0xd38a70>,
<MyViewController: 0xd36b50>
)
2009-09-22 19:57:14.115 App[34707:550b] (null)
Anyone have experience with this?
I am seeing some odd UINavigationController stack behavior with just using
[self.navigationController popViewControllerAnimated:YES];
inside of a delegate called out of a tableView:didSelectRowAtIndexPath: call.
The views don't work right, and a UINavigationController provided "back" operation doesn't correctly pop the view of this delegate, going back another level.
I found that if I used
[self.navigationController popToViewController:self animated:YES];
instead, that suddenly everything worked fine. This is in an application with ARC turned on.
So, I can only guess that there is some reference housekeeping that doesn't happen correctly unless you tell it to pop back to a specific view controller when you will pop a view controller that will immediately become "unreferenced" by that pop.
I fixed it. The code that was popping the view was getting called in viewDidLoad. This meant it was getting popped before the view had actually animated in completely.
I moved that code to viewDidAppear and now it works as advertised.
[[self navigationController] popViewControllerAnimated:NO];
//here you pop **self** from navigation controller. And now
[self navigationController] == nil;
// And
[nil viewControllers] == nil
Try to do this:
UINavigationController *nc = [self navigationController];
NSLog(#"%#", [nc viewControllers]);
[nc popViewControllerAnimated:NO];
NSLog(#"%#", [nc viewControllers]);
What is wrong with?
[self.navigationController popViewControllerAnimated:NO];
Also, you may want to check how you push the ViewController onto the stack. Something doesn't sound right.
I'm having an incredibly frustrating problem that appears to be a bug, but I have a very hard time believing no one else has come across this. My application's root view controller is a UITabBarController, where each tab is a UINavigationController. Everything works great.
Now I've come to a place where I want to edit the stack, so I rearrange the viewControllers of the current navigation controller and then do:
[self.navigationController setViewControllers:newViewControllers animated:YES];
The stack is correctly popped/pushed to the top view controller, but the navigation bar does not update to the current view controller and seems to remain exactly as it did with the viewController before the pop. If I do:
[self.navigationController popToViewController:someViewController animated:YES];
Everything works perfectly. Has anyone ever come across this before? Is there a workaround? Something I'm doing wrong?
I faced the same problem, it seems that Apple haven't corrected that bug and as a result the selected answer of this thread appears to be incorrect.
I managed to correct this problem using this bug report as in the comment of Anurag combined with the comment of Scott Pfeil.
Here is the code :
navController.navigationBarHidden = YES;
NSArray* viewControllers = navController.viewControllers;
UIViewController* currentController = [viewControllers objectAtIndex:viewControllers.count-1];
NSArray *controllers = [NSArray arrayWithObjects: viewController , currentController , nil];
[navController setViewControllers:controllers animated:NO];
navController.navigationBarHidden = NO;
I call this code in the viewDidLoad of the currentController and what I did is replace the previous controllers with only viewController.
Hope this helps.
Apple appears to have fixed this in the newest SDK
Two equally ugly work arounds.
First,
If:
[self.navigationController popToViewController:someViewController animated:YES];
Works well, try pushing an extra viewcontroller on the stack and then call:
[self.navigationController popToViewController:someViewController animated:NO];
Meaning you should get to the vc you want without any animation.
Second,
Before setting the stack, set the leftButtonBarItem = nil;
Effectively removing the old view controller's button. In fact if the title is wrong, change that too.
Neither is exactly clean but may get you the desired results.
You can also set your root view controller as the UINavigationController's delegate like:
#interface YourViewController : UIViewController <UINavigationControllerDelegate> {
and then in the didShowViewController delegate method you manually set the available view controllers:
-(void)navigationController:(UINavigationController*)navigationController didShowViewController:(UIViewController*)viewController animated:(BOOL)animated {
[[viewController navigationController] setViewControllers:[[viewController navigationController] viewControllers]];
}
Let me know if this works in your environment!
I'm still facing this issue in the Xcode 9.4.1 & iOS 11.4 .
The easiest way is to call loadViewIfNeeded() for all previous view controllers in the navigation stack:
let menuViewController = ...
menuViewController.loadViewIfNeeded()
let submenuViewController = ...
navigationController.setViewControllers([menuViewController, submenuViewController], animated: true)
[self.navigationController setViewControllers:newViewControllers animated:NO];
this may help you.