I’ve had a good look at the Apple docs as well as similar Stack Overflow questions, but I am stuck on why my navigationController is null when using tab bars. I am trying to build most of the app from code, and am not using XIBs to insert a navigationController.
While debugging I have greatly simplified my app, down to two tabs. One tab holds a tableview and when a row is touched I’m expecting a detail page (from a XIB) to appear. Should be pretty simple. I am finding the value of self.navigationController is NULL when attempting to push the detail view, and of course it is then not working. I took the tab bar our completely and it works fine from a single view (the tableview). In this instance self.navigationController has a value.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// With Tab Bars
self.tabBarController = [[UITabBarController alloc] init];
ViewController *vc1 = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
vc1.tabBarItem.title = @"Words";
vc1.tabBarItem.image = [UIImage imageNamed:@"tab_feed.png"];
TextTableViewController *vc2 = [[TextTableViewController alloc] init];
vc2.tabBarItem.title = @"Text";
vc2.tabBarItem.image = [UIImage imageNamed:@"tab_live.png"];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:vc1];
NSArray* controllers = [NSArray arrayWithObjects:vc2, navController, nil];
tabBarController.viewControllers = controllers;
tabBarController.delegate = self;
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = self.tabBarController;
[window makeKeyAndVisible];
return YES;
}
From TextTableViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
TextViewController *detailViewController = [[TextViewController alloc] initWithNibName:@"TextViewController" bundle:nil];
Text *text = [[Text alloc] init];
text = [textArray objectAtIndex:indexPath.row];
detailViewController.TextID = text.textID;
NSLog(@"Nav Controller: %@",self.navigationController);
[self.navigationController pushViewController:detailViewController animated:YES];
NSLog(@"pushed");
}
I’ve also got two questions related to this problem.
(1) What is the purpose of this line. It doesn’t appear to make a difference if it is in or out, and is absent from the Apple example.
tabBarController.delegate = self;
(2) When creating an array of tabs, one of the views is made the navigationController. Does it matter which tab it is or should this be a different view altogether not related to any tab and not visible. Is this where the problem lies?
In answer to question (1) about the tab bar controller’s delegate, see the UITabBarControllerDelegate protocol reference. For the basic functionality of a tab bar controller, you don’t need to bother with a delegate.
But let’s say you want to do something special–for instance, save a document or reset an interface element to a default value–when the user changes tabs. You could make one of your classes, perhaps your app delegate or another controller class, conform to the UITabBarControllerDelegate protocol and implement tabBarController:didSelectViewController:
In your “answer” you asked if each tab will need its own UINavigation controller. That is absolutely correct. Basically, each tab is a completely independent hierarchy, so you need a separate UINavigation controller in each tab that requires one.
This should also imply the answer to your question (2) in the original post. You need to add the nav controller to the specific tab(s) that needs it.