I have been using navigation view controller for some time now, and it really does great job. Problem is I don't fully understand it. Maybe some experienced members can shed some light on this topic. I have several questions:
1) Every class that extends UIViewController, has a property navigationController. Apple doc states this -"Only returns a navigation controller if the view controller is in its stack". Does this mean that this property is nil, if this controller is root controller.
2) When using method [self.navigationController pushViewController:nextController animated:YES] nextController is pushed to stack. If you then call self.navigationController inside nextController will navigationController property be nil?
3) Does every navigationController have its own stack, or there is shared stack for all controllers?
4) Finally what happens to items on the stack if you dont pop them, but release navigation controller? Lets say you do push, push, push, and then do release on navigationController. Do these objects stay on the stack or are they destroyed?
1) yes
2) no
3) Every navigationController have its own stack
4) When you push a view controller, navigation controller retains it. When navigation controller is released, then it releases all view controllers in the stack.
Related
So I have a normal UINavigationController with its rootViewController set in the storyboard. Whenever I replace the navigation controller (don't ask why, but certain transitions in my app require the entire stack to be replaced with the new controller) using
var newController: UIViewController!
// newController is initiated at some point
...
if let navigationController = self.navigationController {
navigationController.setViewControllers([newController])
}
And I can visually see the transition occur, but neither the viewWillDisappear or viewDidDisappear methods are called. When I subsequently replace the navigation controller stack they're called as expected. Is there something special about the root the prevents them from being called?
Basically Navigation controller works as a stack of controllers where child controllers go on top of the stack.
If you want to remove a deck of view controllers from a navigation controller, you should use the pop method on their root:
navigationController?.popViewController(animated: true)
This will pop everything out of the stack and you will be able to replace the root with other controllers.
This other answer: How to detect if view controller is being popped of from the navigation controller? expands on the different options you have to detect when your controller gets popped e.g. use isMovingFromParentViewController.
Consider this code to push a new controller onto the nav stack:
AlphaColorController * a = [[AlphaColorController alloc] initWithColor:color name:name alpha:0.25];
[[self navigationController] pushViewController:a animated:YES];
[a release];
There is no pointer kept for a. If a user navigates into this new controller, then navigates "back", and then "forward" again, is the nav controller smart enough to know this controller is already there, or if it isn't, to allocate it again? How necessary is it to first test (using a pointer) if the controller has been instantiated yet before pushing it multiple times?
UPDATE: putting it another way, will this code effectively re-allocate the controller every single time the user navigates into that particular area of the nav controller? the nav controller is going to rereate and push the newly created controller every time?
I don't think you understand how your code is operating. You are, in fact, creating the new view controller object you speak of, and you are, in fact, pushing it onto the nav stack. And what do you mean not keeping a pointer to it? That little star ain't there for nothin'!
NavigationControllers keep a reference to their navigation stacks until such a time as a view is popped off the stack. In which case, said view is deallocated and destroyed.
When a navigation controller push a view controller, the pointer of the view controller will be added into the stack of the navigation controller. So the retain counter +1
The the navigation controller keeps all references of the view controllers it pushed.
I have a project based on Xcode's NavigationController template. This template has a navigationController and a RootViewController.
From inside this RootViewController I push a view and this view pushes a third view. Something like:
NavigationController >> RootViewController >> ViewController 1 >> ViewController 2
Now, from ViewController2 I want to access the navigationController and the navigationController.toolbar.
I know that every viewController has the navigationController property but my question do I have to do something when I push a new viewController so this variable (on the view that is being pushed) will have a valid reference to the correct ViewController or all pushed views will always have a valid reference to the navigationController?
The reason for my question is that I am trying to access the navigationController.toolbar, to make it invisible, and I am having no result.
thanks.
You might want to try -[UINavigationController setToolbarHidden:animated:] to hide the toolbar instead:
[self.navigationController setToolbarHidden:YES animated:YES];
This has always worked for me no matter how deep in the navigation stack my view controller was.
In the entire navigation stack of one UINavigationController object, every view controller's navigationController property has the same value.
The navController is like a box that contains the viewControllers within, with the last one to be pushed shown to the user until it is popped off, when the one below it will come to life again.
This means you can rely on the navController instance always being available from within a controller that was pushed by the navController.
I push new view controller like this.
[self.navigationController pushViewController:resultViewController animated:YES];
but in the resultViewController, i do the same thing like
[self.navigationController pushViewController:resultViewController2 animated:YES];
But I'm not sure I'm doing right. Cuz I think the two navigationController instance should be same.
I know that navigationController is a pointer but not sure those two are pointing same thing.
Cuz to manage view stacks, views should be pushed in one navigationController. Am I right?
Then how do I get the top navigationController from resultViewController class?
or is all process automatic somehow? like by setting pushed viewController's navigationController to self(navigationController pointer) when pushViewController method called? So I can just get self.navigationController and push another new viewController?
It's automatic. a navigation controller is the same throughout all the views in it's stack. So calling self.navigationcontroller in any of those views would be a pointer pointing to the same navigation controller
I have a Navigation Controller with a root table view which has several links. Tapping each link moves to the next view (by pushing it to the navigation controller's stack). But suppose that in that "next view", I have a UIButton that should take me further to another view (by pushing on to the same navigation controller's stack)...
View Controller-->first view-->second view-->third view..........
Now, I can easily access the Navigation Controller when I deal with the first view (and successfully push it to the Navigation Controller's stack) because it has been instantiated in the same file itself. What my real doubt is--How do you access a Navigation Controller in a far off view controller (eg, the third view or fourth view etc)? Please note that I am not using any separate delegate. All the Navigation Bar methods have been implemented in one file and connected to the Navigation Controller via an outlet.
When you push a ViewController onto a NavigationController the ViewController will automatically have it's navigationController property set. This means you can access the same NAvigationController no matter where you are in the stack.
-Update-
navigationController
In every UIViewController you can access that property.
So to in any other UIViewController that has been pushed onto the stack you should be able to just do this:
[self.navigationController pushViewController:othercontroller animated:YES];
Look at the documentation for UIViewController to see what other magic properties you have available.