Why is self.navigationController null in viewDidLoad? - iphone

I know there are a lot of similar questions, but I can't find one that specifically addresses this.
Why is self.navigationController null when called in viewDidLoad, but correct when called from outside viewDidLoad?
This is my output from NSLog(#"%#",self.navigationController); The first is called in viewDidLoad, the second I add a button to the interface with a method that calls NSLog(#"%#",self.navigationController);:
NavApp[31524:11003] (null)
NavApp[31524:11003] <UINavigationController: 0x6e21190>
I know there must be some simple explanation for this behavior, I'm just curious as to what it is. Thanks!

A view controller's view is loaded when you first access the -view method/property on that controller. After the view has been loaded, the viewDidLoad method is called. This is pretty straight forward. You also have to remember that the view can be loaded/unloaded multiple times if memory warnings are received while the view is off-screen.
So viewDidLoad does not mean your view controller has been inserted into a navigation controller. In the process of pushing a view controller onto a navigation controller, its view will be accessed and loaded, but this will happen before the whole push is complete. So viewDidLoad is clearly getting called before the navigationController property has been updated.
You also have to consider that some other part of your code could be accessing the view controller's view before you even push the view controller onto the navigation controller.
So viewDidLoad is the wrong place to do what you are doing. You probably want to use a method like viewDidAppear: so you know that the view controller's view is part of the view hierarchy when it is invoked.

Related

View customization in a pushed view controller

For a controller that is pushed by a nav controller, if in its desired init method you create the details of the pushed controller's view, my understanding is that if the view is removed later because it is offscreen (due to low memory, for example), you may never see it again since the init is only called once when loading the view controller, and subsequent pushes may show nothing.
It would seem a better place for this view setup is in the viewDidLoad or viewWillAppear, that way it will be recreated correctly if the controller needs to build the view the next time it is pushed.
Yet I see tutorials that often put the pushed view controller's view setup in its init method; how important is this?
View setup should be done in viewDidLoad (or in loadView if you're not using a nib), for exactly the reason you're describing. If you need to know the controller's top-level view dimensions to set up the subviews, then do it in viewWillAppear:.
Usually, a view controller that is popped is immediately deallocated; if the app needs to show the same view later, it creates a new view controller for it. So in that scenario, the app won't show “nothing”.
If the app pushes or presents another view controller on top of the first view controller, the first view controller's view can be unloaded. If the app never pushes or presents a second view controller over the first view controller, the first view controller's view can't be unloaded until the controller is popped, at which time (in most apps) the controller is deallocated anyway. So in that case, setting up the view in init won't cause trouble.
But it's still bad design to set up views in init. You might change your app later to push or present a second view controller, thus creating unexpected unsafe behavior.
Also, it's common to create a view controller, set properties on it, and then push it. If the properties affect the controller's view hierarchy, then init is too early to set up the views.

When is viewWillAppear called?

By my count, the only two instances when viewWillAppear is called is when you initialize your view controller, or when you pop off the view controller that's on top of it on the navigation stack (ie pushing the back button on the viewcontroller ahead of it). Are there any other instances when viewWillAppar is called? I don't believe it's called when the app becomes active. Interested to hear some responses on this.
viewwillappear method is called as and when the view controller's view is added to the window. ( if the view is already in the window and is hidden by another view, this method is called when the view is once again revealed). The method is a notification to the view controller that the view is about to become visible. You can override this method to make any customizations with presenting the view.
This will also be called anytime addSubView is called, with your view.

How to pop to rootview controll without using popToRootViewControll method?

How to pop to rootview controll without using popToRootViewControll method because this method does not implement viewDidLoad method of RootViewController???
What do you mean by "because this method does not implement viewDidLoad method of RootViewController"?
The "viewDidLoad" is called only one time if you don't have memory warning. If you get an memory warning your viewDidLoad method is called again.
You need to implement your logic in "viewWillAppear".
And maybe you should read View Controller Programming Guide for iOS
UIViewController Class Reference here you find the viewWillAppear, and viewDidAppear methods
I think you need to take a different approach to solving this problem.
If you have code in the root view controller's viewDidLoad method that you want to run again, then that code shouldn't be in the viewDidLoad method in the first place. viewDidLoad only runs just after the view controller's view is loaded (usually just once in the lifetime of the view controller). You should probably put that code it in its own method in the view controller, so you can still call it from the viewDidLoad method.
To have the code run when you pop to the root view controller, you can call that new method from the root view controller's viewWillAppearAnimated method, which gets called each time the view controller's view is about to be displayed.

viewWillAppear only being called once

Here's the scenario, switchViewController is the view added to the main window. So switchViewController is the main view, so if I want to go view B, I will addsubview of view B, there isn't a need to remove switchViewController's view right?
The issue is after I go back from view B to switchViewController's view, the method viewWillAppear is not being called anymore.
Why is it so?
viewWillAppear: is not called automatically when a view is removed from or added to the view hierarchy. It is the responsibility of the view controller to call it at the right time. The built-in view controller classes do this whenever you present or push a new view controller. Since you do not use this mechanism in your app, the method doesn't get called (unless you call it yourself).
That's because it never disappeared, you were just putting something else in front of it. If you want to navigate from one screen to another and back, they should be separate view controllers, and you should be using UINavigationController and its pushViewController:isAnimated: method.
It's not getting called beause your just modifying the first view, not navigating to a different one.
You might consider embedding your view in a Navigation controller, then calling your ViewB with
[navigationController pushViewController:viewB animated:YES];

Push View Controller into Navigation Controller

Some times when I push ViewController into Navigation Controller,
the viewDidLoad() method of the View Controller is not called.
And this cause my application to crash. I would appreciate any help.
I forget to mention that I load the view from the nib before I push it to the Navigation Controller.
Thanks,
Sarah
The viewDidLoad method is only called when the view is first loaded from the Nib file. If the view was already loaded and you push the view again it will not fire again.
Depending on what you want to do, you may want to use viewWillAppear or viewDidAppear instead.
Once the View is loaded and added to the Controller's stack, you will not see this called again. You would need the view to get popped off the stack and pushed again to see it. You can always be assured viewWillAppear will get invoked everytime you return to the view. This allows you to do any housekeeping that may be in order (which i assume is the goal).