(This is both question and answer since it took quite a bit of digging to find the real answer.)
Symptom: viewWillAppear
, viewDidAppear
were not being called in my UIViewController.
Cause: Embedding a UINavigationController
or UITabBarController
(my case) in a UIViewController
somehow interrupts with the calling of these methods.
Solution: Call them manually in the UIViewController
that contains the aforementioned UINavigationController
/ UITabBarController
.
For example (assuming projectNavigationController
is your UINavigationController
):
-(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [projectNavigationController viewWillAppear:animated]; } -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [projectNavigationController viewWillDisappear:animated]; } -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [projectNavigationController viewDidAppear:animated]; } -(void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [projectNavigationController viewDidDisappear:animated]; }
In my case I had an inner UITabBarController
and I called the methods accordingly and all was solved.
(Attribution on the solution: http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/)
I'm going to go ahead and disagree with @St3fan, and use UIKit
as the counter-example.
However, the wisdom (or lack thereof), of embedding controllers in general should be guided by sane UI design principles.
The easiest counter-example is UINavigationControllers
embedded in UITabBarControllers
. These appear all over the place. Just off the top of my head, the iPod app on iPhone, and Contacts within the Phone app on iPhone.
I was curious enough to bother to check what they do with the views (add to the "super-controller" view or to the UIWindow
. I was pretty sure I was going to find that the sub-controller views were descendants of the super-controller views in the view hierarchy, which is contrary to St3fan's recommendation.
I whipped up a very quick iPhone app hooking everything up in InterfaceBuilder to create a UITabBarController
based app with two tabs, the first of which was a UINavigationController
with a plain ole UIViewController
as it's root view controller, and a 2nd tab with a plain old UIViewController
just so I had a 2nd tab to click later.
Sprinkle in some NSLog
statements to output the various UIView's
for the controllers we see this:
tabBarController.view = <UILayoutContainerView: 0x5b0dc80; ...
navigationController.view = <UILayoutContainerView: 0x59469a0; ...
rootViewController.view = <UIView: 0x594bb70; ...
Superview: <UIViewControllerWrapperView: 0x594cc90; ...
Superview: <UINavigationTransitionView: 0x594a420; ...
Superview: <UILayoutContainerView: 0x59469a0; ... // navigationController.view
Superview: <UIViewControllerWrapperView: 0x594b430; ...
Superview: <UITransitionView: 0x5b0e110; ...
Superview: <UILayoutContainerView: 0x5b0dc80; ... // tabBarController.view
Superview: <UIWindow: 0x5942a30; ...
The lines prefixed with "Superview" were the output from walking up the rootViewController.view's
superview chain until hitting nil.
Then of course a quick glance at the call stack in a couple of places where viewDidDisappear
would get called on the root view controller.
First, the call stack when viewDidDisappear
is called on the root controller as a result of a new controller being pushed on to the stack:
-[RootController viewDidDisappear:]
-[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]
...
Second, the call stack when another tab is selected in the top-most UITabBarController:
-[RootController viewDidDisappear:]
-[UINavigationController viewDidDisappear:]
-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:]
So in all cases, it seems that Apple decided that controllers should be calling the various viewDidAppear
, etc methods on their embedded subcontrollers and that the view's should be embedded similarly. I think the OP hit this nail right on the head if we're to take UIKit
design as a good lead to follow.