I have am setting up my application like so (in applicationDidFinishLaunching):
mytable = [[[MyTableController alloc] initWithStyle:UITableViewStylePlain] retain];
UINavigationController *mynav = [[[UINavigationController alloc]initWithRootViewController:mytable] autorelease];
[mynav.view setFrame:CGRectMake(0,0,320,460)];
UIViewController *tab1 = [[tabBarController viewControllers] objectAtIndex:0];
[mytable setTitle:#"Chronological"];
mytable.navigationController = mynav;
[tab1.view addSubview:mynav.view];
[window addSubview:tab1.view];
where MyTableController extends UITableController and has a navigation controller property. tabBarController is an outlet via the main nib file. There are no other nib files.
I am now unable to add any buttons to the navigation controller. Everything I do is ignored. What am I doing wrong here?
Can you include the code where you set up the UITabBarController tabBarController? I'm guessing that you are not properly setting the viewControllers property. Use UITabBarController -setViewControllers:animated: with an array of view controllers to initialize the tab bar controller.
Try something like this:
mytable = [[MyTableController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *mynav = [[UINavigationController alloc] initWithRootViewController:mytable];
[tabBarController setViewControllers:[NSArray arrayWithObject:mynav] animated:NO];
[mynav release];
[mytable release];
[tabBarController viewWillAppear:NO];
[window addSubview:[tabBarController view]];
[tabBarController viewDidAppear:NO];
Related
How to create a tabbar Controller and Navigation Bar Controller in a window based app? I am trying to include both controllers.
You can do this as follows...
Create project of navigationController type..
then in AppDelegate , create a tabBarController. Have an array of you Viewcontrollers as follows...
mTabBar = [[UITabBarController alloc] init];
NSMutableArray *localViewControllersArray = [[NSMutableArray alloc] initWithCapacity:3];
TSDetailTaskController *mTSDetailTaskController = [[TSDetailTaskController alloc]initWithNibName:#"TSDetailTaskController" bundle:nil];
UINavigationController *mTaskNavBar=[[UINavigationController alloc]initWithRootViewController:mTSDetailTaskController];
mTaskNavBar.tabBarItem.title=#"Task List";
mTaskNavBar.tabBarItem.image =[UIImage imageNamed:#"glyphicons_114_list.png"];
[mTSDetailTaskController release];
mTSSearchController=[[TSSearchController alloc]initWithNibName:#"TSSearchController" bundle:nil];
UINavigationController *mSearchNavBar=[[UINavigationController alloc]initWithRootViewController:mTSSearchController];
mSearchNavBar.title=#"Search";
mSearchNavBar.tabBarItem.image=[UIImage imageNamed:#"glyphicons_009_search.png"];
[mTSSearchController release];
TSSettingController *mTSSettingController = [[TSSettingController alloc]initWithNibName:#"TSSettingController" bundle:nil];
UINavigationController *mSettingNavBar=[[UINavigationController alloc]initWithRootViewController:mTSSettingController];
mSettingNavBar.tabBarItem.title=#"Setting";
mSettingNavBar.tabBarItem.image=[UIImage imageNamed:#"glyphicons_280_settings.png"];
[mTSSettingController release];
[localViewControllersArray addObject:mTaskNavBar];
[localViewControllersArray addObject:mSearchNavBar];
[localViewControllersArray addObject:mSettingNavBar];
[mTaskNavBar release];
[mSearchNavBar release];
[mSettingNavBar release];
mTabBar.viewControllers = localViewControllersArray;
mTabBar.view.autoresizingMask==(UIViewAutoresizingFlexibleHeight);
[localViewControllersArray release];
[window addSubview:mTabBar.view];
[self.window makeKeyAndVisible];
return YES;
hope this will help you out..
Instead of viewcontrollers, add navigation contollers as each item for the tabbarcontroller.
You can also do it in the Interface Builder, just make sure the Tabbar controller is the root/master controller and inside it you can add as many navControllers as you need. Of course, the tabbar controller is the one added to the Window in the AppDelegate.m file.
I you dont want the tabbar to be visible from the begining, you can implement self.tabbarcontroller.tabbar.hidden = YES; in the viewDidLoad or viewWillAppear methods of each of the views you dont want the tabbar on.
I want to push root view controller. Why doesn't this code work?
RootController *rootController = [[RootController alloc]initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:rootController animated:YES];
[rootController release];
I used addSubview like this before.
- (void)cancel {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)viewDidLoad { // this is root view controller
[super viewDidLoad];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancel)];
self.navigationItem.leftBarButtonItem = cancelButton;
[cancelButton release];
}
RootController *rootController = [[RootController alloc]initWithStyle:UITableViewStylePlain];
UINavigationController *aNavigationController = [[UINavigationController alloc]initWithRootViewController:rootController];
self.naviController = aNavigationController;
[aNavigationController release];
[rootController release];
[self.view addSubview:[naviController view]];
And I added cancel button in navigation bar to go back to previous view. It doesn't work.
So, I want to push instead of add.
You set the root controller in a UINavigationController using the
initWithRootViewController:
method. So, the way you are doing is correct. I would suggest you to inspect self.view and ensure that it is not nil.
EDIT: after your comment
You need to define a root view controller for your UINavigationController to work properly; from the UINavigationController reference:
Every navigation stack must have at least one view controller to act as the root.
So you cannot remove the root view controller. Possibly, to make things work as you like you should create an additional view controller to use as root view controller that you do not alter, then push your RootViewController on the navigation stack, then popping would work:
UIViewController *baseController = [[UIViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:baseController];
self.naviController = aNavigationController;
[aNavigationController release];
[baseController release];
[self.view addSubview:[naviController view]];
RootController *rootController = [[RootController alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:rootController animated:YES];
[rootController release];
Notice that I first defined a simple UIViewController as root view controller, then pushed your controller on to it.
Once you do this, if you add the cancel button like you do, it will work popping the rootViewController from the navigation stack.
AFTER LAST COMMENT:
If I understand you right, when clicking on the cancel button, you want to get rid of the UINavigationController altogether.
In this case, use the following code for cancel:
- (void)cancel {
[self.navigationController.view removeFromSuperview];
}
If this guess is right, keep in mind that since you are not keeping any reference to the navigation controller, it will be deallocated and with it all the view controllers you instantiated.
If instead of removing the UINavigationController altogether, you would simpy hide the navigation bar, then after popping rootController, call:
setNavigationBarHidden:animated
I've been stuck trying to puzzle this out for a couple days now, and I'll admit I need help.
The root view controller of my application is a tab bar controller. I want to have each tab bar a different navigation controller. These navigation controllers have completely different behavior.
So how do I set this up in terms of classes? Per Apple's documentation, I'm not supposed to subclass UINavigationViewController. So where do I put the code that drives each of these navigation controllers? Does it all get thrown in App Delegate? That would create an impossible mess.
This app should run on iOS 4.0 or later. (Realistically, I can probably require iOS 4.2.)
This is taken from one of my applications. As you say, you are not supposed to subclass UINavigationController, instead you use them as they are and you add viewcontroller on the UINavigationController's. Then after setting the root viewcontroller in each UINavigationController, you add the UINavigationController to the UITabBarController (phew!).
So each tab will "point" to a UINavigationController which has a regular viewcontroller as root viewcontroller, and it is the root viewcontroller (the one you add) that will be shown when a tab is pressed with a (optional) navigationbar at top.
UITabBarController *tvc = [[UITabBarController alloc] init];
self.tabBarController = tvc;
[tvc release];
// Instantiates three view-controllers which will be attached to the tabbar.
// Each view-controller is attached as rootviewcontroller in a navigationcontroller.
MainScreenViewController *vc1 = [[MainScreenViewController alloc] init];
PracticalMainViewController *vc2 = [[PracticalMainViewController alloc] init];
ExerciseViewController *vc3 = [[ExerciseViewController alloc] init];
UINavigationController *nvc1 = [[UINavigationController alloc] initWithRootViewController:vc1];
UINavigationController *nvc2 = [[UINavigationController alloc] initWithRootViewController:vc2];
UINavigationController *nvc3 = [[UINavigationController alloc] initWithRootViewController:vc3];
[vc1 release];
[vc2 release];
[vc3 release];
nvc1.navigationBar.barStyle = UIBarStyleBlack;
nvc2.navigationBar.barStyle = UIBarStyleBlack;
nvc3.navigationBar.barStyle = UIBarStyleBlack;
NSArray *controllers = [[NSArray alloc] initWithObjects:nvc1, nvc2, nvc3, nil];
[nvc1 release];
[nvc2 release];
[nvc3 release];
self.tabBarController.viewControllers = controllers;
[controllers release];
This is how I go from one viewcontroller to another one (this is done by tapping a cell in a tableview but as you see the pushViewController method can be used wherever you want).
(this is taken from another part of the app)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.detailedAnswerViewController == nil) {
TestAnsweredViewController *vc = [[TestAnsweredViewController alloc] init];
self.detailedAnswerViewController = vc;
[vc release];
}
[self.navigationController pushViewController:self.detailedAnswerViewController animated:YES];
}
The self.navigationcontroller property is of course set on each viewcontroller which are pushed on the UINavigationController hierachy.
I am editing my question that i had programetically add the tabbar as shown below:-
FirstViewController *obj_FirstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *obj_SecondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
ThirdViewController *obj_ThirdViewController = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
navigation1 = [[UINavigationController alloc] initWithRootViewController:obj_FirstViewController];
navigation2 = [[UINavigationController alloc] initWithRootViewController:obj_SecondViewController];
navigation3 = [[UINavigationController alloc] initWithRootViewController:obj_ThirdViewController];
MainTabBar = [[UITabBarController alloc] init];
MainTabBar.delegate=self;
[MainTabBar setViewControllers:[NSArray arrayWithObjects:navigation1,navigation2,navigation3,nil]];
MainTabBar.view.frame=self.view.frame;
MainTabBar.selectedIndex=0;
[self.view addSubview:MainTabBar.view]
By writing this in (void)viewDidLoad i got the 3 tab in my viewcontroller.But the problem is i want to set the name of the tab as
Home
Favorites
About us
I had tried by writing the below code:-
obj_FirstViewController.tabBarItem.title=#"Home";
self.title = #"My View Controller";
But this does not work - can anyone please help me how to do this programatically? Where to write the line so that i get this 3 name in my tab bar
this is how I made it
1) I made a view controller with your tabbar
2) added view controllers for each tab and a method to the tabbar view controller class:
-(void)updateContentsWithViewController:(UIViewController *)insideViewController
the method is called when a tabbutton is pressed.
3) here is the code for the switching
- (void)updateContentsWithViewController:(UIViewController *)insideViewController {
//internalViewController is the viewController which you change
[internalViewController.view removeFromSuperview];
[internalViewController release];
internalViewController = [insideViewController retain];
navController = [[UINavigationController alloc] initWithRootViewController:insideViewController];
[navController setNavigationBarHidden:YES];
[navController.view setFrame:CGRectMake(0, 0, 320, 348)];
//frame I needed in my app .. can be changed
[self.internalView addSubview: navController.view];
//navController is the property for the navigationController
[self.view sendSubviewToBack: self.internalView];
}
its possible add tabBar in separate view controller which will be like rootview controller ,then in viewDidLoad of the root view controller assign the object of tabbar created to a appdelegate tabBar declared ...then use appdelegate tabbar for other navigation's alone .
I am working with push notifications. i am trying to create and push a DetailView in the navigationController when action button in notification is clicked. but navigationController is nil. how can i put that DetailView in the navigationController? I want to push RootViewController in the navigationController and then the DetailView. how can i do that?
in AppDelegate:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
RootViewController *controller = [[RootViewController alloc] init];
//getting warnings here.(Unused variable navigationController)
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
[controller doStuff];
[controller release];
}
in RootViewController:
-(void)doStuff{
[[self stories] removeAllObjects];
[self startParsing];
[self.tableView reloadData];
DetailViewController *detail = [[DetailViewController alloc] init];
//custom code
[self.navigationController pushViewController:detail animated:YES];
[detail release];
this is the code i m using right now. and plz notice that i have
[self.tableView reloadData];
Okay, now I am pretty sure I understand the issue. The problem is, you never manually set the navigationController property on a UIViewController. The navigationController property is nil if the view controller is not under a navigation controller and if it is, then the property points to it.
What you need to do, is when you display your root view controller, instead of directly displaying its view, add it to a navigation controller, then display the navigation controller's view. Like so:
RootViewController *controller = [[RootViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
//Here you would display navigationController.view somehow
So, after you have your root view controller in a navigation controller, in a method in root view controller you can do this:
DetailViewController *detail = [[DetailViewController alloc] init];
//Do whatever you need to do to set values on the detail view controller
[self.navigationController pushViewController:detail animated:YES];
The key thing is this: you need to put the root view controller into a navigation controller before you can access a navigation controller from within root view controller.
If your nav controller is nil, it needs creating and then you place things into it.
Try this:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[navController pushViewController:detailViewController animated:NO]; // or YES
If you start out with no UINavigationController and want to display it with more than one view controller in its stack, after initing the navigation controller you can set the viewControllers property to an array with the various view controllers you want.
edit: some example code:
UINavigationController *navController = [[UINavigationController alloc] init];
NSArray *viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
[navController setViewControllers:viewControllers animated:NO];
After doing that, your navigation controller will have viewController2 on top and viewController1 behind it.
Alternately, you could do it this way:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController1];
[navController pushViewController:viewController2 animated:NO];