As an overview, I'm having issues with a UINavigationController inside of a UITabBarController calling viewWillAppear whenever a view is popped from the stack.
From the delegate, a UITabBarController is made programmatically:
// Create views for Tab Bar
UINavigationController *view1 = [[UINavigationController alloc] initWithRootViewController:[[newsFeedNavigationController alloc] initWithStyle:UITableViewStylePlain]];
resizedTabBatItem *tabBarItem1 = [[resizedTabBatItem alloc] initWithTitle:nil image:[UIImage imageNamed:@"newspaper.png"] tag:0];
[view1 setTabBarItem:tabBarItem1];
[tabBarItem1 release];
UIViewController *view2 = [UIViewController new];
resizedTabBatItem *tabBarItem2 = [[resizedTabBatItem alloc] initWithTitle:nil image:[UIImage imageNamed:@"speechbubble.png"] tag:1];
[view2 setTabBarItem:tabBarItem2];
[tabBarItem2 release];
....
// Create the tab bar controller
bookTabBarController = [BookTabBarController new];
[[bookTabBarController view] setFrame:CGRectMake(0, 0, 320, 460)];
// Add the views to it
NSArray *viewControllers = [NSArray arrayWithObjects:view1, view2, view3, view4, view5, nil];
[[bookTabBarController tabBarController] setViewControllers:viewControllers];
My newsFeedNavigationController is just a subclassed UITableViewController (and the subclass is not interfering with viewWillAppear, as it's never called in newsFeedNavigationController). In it, items that when clicked will push a new UIViewController into the stack.
The problem is that whenever views are popped off the stack, viewWillAppear is never called in newsFeedNavigationController, and the items in the list remain highlighted. I've been messing with this for a few hours am at the point where I need some help to find out what I am doing wrong.
In my newsFeedNavigationController, I tried to add an NSLog to see if it is called or I did something, but it is never even called.
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"is viewWillAppear called?");
[super viewWillAppear:animated];
}
Edit:
Okay, now here is something weird I noticed:
If I run:
[self presentModalViewController:(any UIview) animated:YES];
and then dismiss it, viewWillAppear begins to work properly when popping and pushing views... So now I am stumped. It's not really a solution but maybe an inside of something that is going on.
The Simple Answer. The technical reason for when viewWillAppear gets called is simple. Notifies the view controller that its view is about to be added to a view hierarchy. It can't be any view hierarchy — it has to be the one with a UIWindow at the root (not necessarily the visible window).
The method viewWillAppear: is triggered in response to a change in the state of the application, indicating that the view controller is becoming “active.” The reason viewDidLoad exists – the only reason – is that it sometimes isn't possible or efficient to configure 100% of an interface in a XIB.
To answer my own question, I found out what the problem was.
In order to abide by Apple's "No UITabBarController inside of a UINavigationController" I wrote my own tab bar controller (bookTabBarController) which is based off of a standard View Controller. My problem was that the class wasn't passing viewDidAppear down to the class that managed the view controllers, so it never knew it was being shown or not.
Another solution is to set the navigation controller's delegate. Within the delegate, implement the following method:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[viewController viewWillAppear:animated];
}
This will ensure that viewWillAppear will get called on any view controller whose view is about to appear in the navigation controller. If you do it this way, viewWillAppear gets called regardless of whether the view is appearing because it is being pushed, or it is appearing because a subview is being popped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With