Reputation: 551
I'm trying to create a container view controller to hold a UINavigationController and a custom UIViewController together on screen.
I laid it out in a test program and it works perfectly, however when I tried to implement it in my real project the appearance methods for the containing View Controllers never get called.
Working Test:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
MasterStatusViewController *master = [[MasterStatusViewController alloc] init];
[self.window setRootViewController:master];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
InventoryViewController *newInventory = [[InventoryViewController alloc] init];
self.navigation = [[UINavigationController alloc] initWithRootViewController:newInventory];
self.statusRibbon = [[StatusBarViewController alloc] initWithNibName:@"StatusBarViewController" bundle:nil];
[self addChildViewController:self.navigation];
self.navigation.view.frame = self.navigationView.frame;
[self.view addSubview:self.navigation.view];
[self.navigation didMoveToParentViewController:self];
[self addChildViewController:self.statusRibbon];
self.statusRibbon.view.frame = self.ribbonView.frame;
[self.view addSubview:self.statusRibbon.view];
[self.statusRibbon didMoveToParentViewController:self];
}
Failing Project:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
MasterViewController *master = [[MasterViewController alloc] init];
self.centerController = master;
[self.window setRootViewController:master];
[self.window makeKeyAndVisible];
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
LoginViewController *login = [[LoginViewController alloc] init];
self.navigation = [[UINavigationController alloc] initWithRootViewController:login];
self.statusRibbon = [[StatusRibbonViewController alloc] init];
[self addChildViewController:self.navigation];
self.navigation.view.frame = self.navigationView.frame;
[self.view addSubview:self.navigation.view];
[self.navigation didMoveToParentViewController:self];
[self addChildViewController:self.statusRibbon];
self.statusRibbon.view.frame = self.ribbonView.frame;
[self.view addSubview:self.statusRibbon.view];
[self.statusRibbon didMoveToParentViewController:self];
}
The views are arranged correctly and perform as expected, except the appearance methods never get called. I'm quite perplexed. Calling the methods manually doesn't seem to be a solution, as those calls aren't going through either.
EDIT: By appearance method I mean viewWillAppear, viewDidAppear, et al.
SECOND EDIT:
~ snip ~
THIRD EDIT: Upon further inspection, I believe the reason the appearance lifecycle methods aren't being called is because they aren't being called on the container view controller either. I added
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"MasterViewController VIEW WILL APPEAR");
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"MasterViewController VIEW DID APPEAR");
}
to the masterViewController
and nothing, for some reason they are never being called.
Upvotes: 0
Views: 3276
Reputation: 797
I had a similar issue where I was using the containment features of UIViewController where the appearance methods were not getting forwarded whenever I added a new child view controller to the view.
It turns out that you need to call beginAppearanceTransition:animated: before you add the sub view and endApperanceTransition when you are done. You will need to do this when you add the sub view and also when you remove it in order to trigger the appearance methods.
For your case, I'd try something like this:
self.navigation.view.frame = self.navigationView.frame;
[self addChildViewController:self.navigation];
[self.navigation didMoveToParentViewController:self]
[self.navigation beginAppearanceTransition:YES animated:NO];
[self.view addSubview:self.navigation.view];
[self.navigation endAppearanceTransition];
self.statusRibbon.view.frame = self.ribbonView.frame;
[self addChildViewController:self.statusRibbon];
[self.statusRibbon didMoveToParentViewController:self]
[self.statusRibbon beginAppearanceTransition:YES animated:NO];
[self.view addSubview:self.statusRibbon.view];
[self.statusRibbon endAppearanceTransition];
Upvotes: 3
Reputation: 551
Solved it. I don't know why the master appearance methods were not being called, a few cleans of xcode seemed to solve that problem.
However, those methods still weren't being forwarded to my other view controllers. Then I came across this link and learned that you always have to forward appearance calls to them no matter what. I was able to fix it by adding:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigation beginAppearanceTransition: YES animated: animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigation endAppearanceTransition];
}
-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigation beginAppearanceTransition: NO animated: animated];
}
-(void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.navigation endAppearanceTransition];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Upvotes: 5
Reputation: 1739
What do you mean exactly by "appearance methods"? You mean, that the view doesn't appear?
In your working example, you're loading the ribbon view from a nib file:
self.statusRibbon = [[StatusBarViewController alloc] initWithNibName:@"StatusBarViewController" bundle:nil];
while you just init
it in the second code example:
self.statusRibbon = [[StatusRibbonViewController alloc] init];
The latter just creates a 'fresh' view, which may result in your perception, that it doesn't appear.
Upvotes: 0