My project is a view based project to start off.
So app delegate launches as per normal.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Then my first viewcontroller is called and it shows two UITextFields so the user can enter their credentials and log on.
When that succeeds I call another view controller in which I add a UINavigationController and a UITabBarController to the view. As can be seen below.
- (void)viewDidLoad
{
[super viewDidLoad];
UINavigationController *localNavigationController;
tabBarController = [[UITabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:2];
Hello *firstViewController;
firstViewController = [[Hello alloc] init];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
[localNavigationController.tabBarItem initWithTitle:#"Test" image:[UIImage imageNamed:#"tabBarIcon.png"] tag:1];
//[localNavigationController.tabBarItem initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:1];
firstViewController.navigationItem.title=#"New Requests";
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[firstViewController release];
Test *secondViewController;
secondViewController = [[Test alloc] init];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:secondViewController];
[localNavigationController.tabBarItem initWithTitle:#"Test" image:[UIImage imageNamed:#"tabBarIcon.png"] tag:2];
secondViewController.navigationItem.title=#"Existing";
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[secondViewController release];
// load up our tab bar controller with the view controllers
tabBarController.viewControllers = localControllersArray;
// release the array because the tab bar controller now has it
[localControllersArray release];
// add the tabBarController as a subview in the window
[self.view addSubview:tabBarController.view];
}
This seems to work ok, so far. There was a problem off both the Navbar and Tabbar being dropped to low by the height of the status bar, but that was corrected once i hid the status bar.
Is there any reason I should not do things this way? Is it bad practice or will i run into some problems with it down the road?
I could set up both the Navbar and the Tabbar from the app delegate and just hide them both during the log-on screen. That's the only other option I see.
I appreciate any feedback that you guys can offer. I feel nervous about the results of what I have done so far, expect it might blow up in my face.
Many Thanks,
-Code
You should generally not directly add the views of UINavigationController and UITabBarController as subviews of your own view controllers. This kind of 'view controller containment' is tricky to get right unless you use the new iOS 5 APIs.
The reason is that the actual view controllers will not receive certain important messages like viewDidAppear: and rotation messages. You will notice strange rotation bugs and other weird issues cropping up. You can forward these methods yourself from the parent view controller and things will work OK, but in your case you have no need to do this because you're just trying to show a standard tab bar controller.
Generally you should have one view controller set up as the UIWindow's root view controller. This is normally a UINavigationController, UITabBarController, etc. The parent UIWindow will send rotation events and other messages to this controller. The standard 'container' controllers like UITabBarController will then forward these messages to their children so everything works correctly.
If I were you, I would always have the tab bar controller as the window's root view controller. When your app starts (i.e. in application:didFinishLaunchingWithOptions:), create an empty tab bar controller and set it up as the root view controller:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// create a basic empty tab bar controller
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
// ...
// Set up the window's root view controller
self.window.rootViewController = tabBarController;
// ...
}
Now, whenever you present stuff on the screen, it should be a child of the root view controller, in your case the tab bar controller.
So once the root view controller is set up, you can check to see if the user is already logged in. If they are, you can then set up your navigation controller and the tab items, and add them to the tab bar controller.
If the user is not logged in, you can show your login view controller over the top of the tab bar controller using presentModalViewController:animated::
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
// Set up the window's root view controller
self.window.rootViewController = tabBarController;
if (isUserLoggedIn()) {
[self setupTabsAndStuff];
} else {
LoginViewController *loginVC = [[[LoginViewController alloc] init] autorelease];
[self.tabBarController presentModalViewController:loginVC animated:NO];
}
// ...
}
The animated:NO will cause the login screen to be immediately visible after starting the app with no animation.
Once the user enters correct details you can again call your setupTabsAndStuff method and dismiss the login view controller again.
So to summarize:
Rather than having your own UIViewController into which you place the tab bar controller's view, just use the tab bar controller directly.
Install the tab bar controller as the window's root view controller. The tab bar controller will then correctly forward rotation events and other special messages to the view controllers it contains.
Always present views and view controllers as children of the root view controller. If you need to show something full-screen use presentModelViewController:animated
Try to set the frame of *tabBarController.
[tabBarController.view setFrame:self.view.bounds];
// add the tabBarController as a subview in the window
[self.view addSubview:tabBarController.view];
Related
I am very new to the iPad UISplitViewController.
I need to add a tab bar containing 3 tabs at the bottom of the master view / left view. I have a different View Controller for each of the 3 tabs. I haven't found any other examples of Tab bars being used in split view based applications.
Where do I insert a tab bar controller for displaying at the bottom of the the root view?
How do I establish a connection so that when I select a table cell, the detailItem info gets displayed in the Detail View? Tab bar was added to the Root View in IB. Should I be adding it programmatically instead?
in your app delegate add tabbar controller then add your view controllers to tabbar controller and set the window rootview controller to tabbar controller.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.tabbar=[[UITabBarController alloc] init];
self.vc1 = [[vc1 alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
// do the same to other VCs
self.tabbar.viewControllers=[NSArray arrayWithObjects:vc1,vc2,vc3,vc4, nil];
self.window.rootViewController = self.tabbar;
[self.window makeKeyAndVisible];
return YES;
}
i hope it helps :-)
you have to take UITabBarController dynaically.
In .h file
UITabBarController *tabBar;
in .m file
create objects to your classes in appDidFinish Launch
For example you have
Class1 and Class2
in appDidFinishLaunch
Class1 *obj1=[Class1 alloc]initWithNibName:#"Class1" bundle:nil];
**Class2 obj2=[Class2 alloc]initWithNibName:#"Class2" bundle:nil];*
// Master navigation controller by defaults comes with template code
// Now you have create Array for tabBar
NSArray *tabViewArray=[[NSArray alloc] initWithObjects:obj1,obj2,masterNavigationController, nil];
tabBar=[[UITabBarController alloc] init];
[tabBar setViewControllers:tabViewArray];
// now you have to edit the statement which contains splitview.viewArray repalce masterNavigataionControler with tabBar
self.splitViewController.viewControllers = [NSArray arrayWithObjects:tabBar, detailNavigationController, nil];
Try this i hope it will helps you.
All you have to do is initialize the first argument of uispliviewcontroller for view as tabbar instead of a view or you can use uisegmentedcontrol.
Before:
My App is based on indepent view controllers. I can switch from one to another by replacing the root view controller on the application delegate:
ade.window.rootViewController = newController;
... and all worked right, till now.
Tomorrow:
we have to add a NavigationController-based part of our App, which will help the users navigate through our:
Brands => Model Names => Colors
So, the user will choose a color, then click a button: now I will switch to another UIViewController (call it "pippo"), which actually resides outside that navigation hierarchy (I can't push it in the nav-controller for several methods, I'm forced doing so!).
What I want is to get back to my "Color" screen, from "pippo". So, I'm looking for a way to programmatically "navigate" the navigation controller I restore, I mean:
I restore my navigation controller
now I'm on Brands, but I don't want my users to be here, I want to show them the last color they was on (I saved it in the preferences)
how can I simulate the selection of a known brand and model?
Thanks a lot.
In applicationDidFinishLoading in App delegate:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[window makeKeyAndVisible];
[window addSubview:navController.view];
That will instantiate the navigation controller and add it to the window as a view.
Now, in your rootViewController class (lets say its called FirstViewController) you can do this:
- (void)clickedAButton:(id)selector {
SecondViewController *nextViewController = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
// and push it onto the 'navigation stack'
[self.navigationController pushNavigationController:nextViewController animated:YES];
// and release
[nextViewController release];
}
And in your SecondViewController you can navigate back through the stack using:
- (void)clickedAnotherButton:(id)selector {
// goes back to the last view controller in the stack
[self.navigationController popViewControllerAnimated:YES];
}
So for you it would go:
Set up navigation controller in the app delegate with Brand as the root view controller
User chooses their brand and you pushViewController:animated: the Model view controller. Then the user chooses their model and you pushViewController:animated: the Color view controller. Similarly the user chooses a color and you push the Pippo view controller. Now, if the user presses back (or you call popViewControllerAnimated:) it will go back to the Color view controller in the same state as when the user left it to go to the Pippo controller.
Write the following code in AppDelegate.m Class
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.nav = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.nav.navigationBarHidden = YES;
[mainViewController release];
[_window addSubview:nav.view];
[_window makeKeyAndVisible];
}
I am Create already three view controller & i want to just add those view controller in tabBarview controller.
The view controller is below
First --> Login Page
Second --> Tabbar View controller
1)---> Employee View controller
2)---> Task View Controller
3)----> Home View controller
I am create above three view controller separate. I want add those in tab bar controller using Interface Builder or coding.
You can find more descriptive example from Apple docs - Combined View Controller Interfaces
I assume that Login Page is your root view controller here. Where _tabBar, _window and _loginvVewController are globally declared in the appDelegate headers files. You can also take _loginvVewController locally inside the didFinishLaunchingWithOptions method depend upon your requirements.
AppDelgate.h
UIWindow *_window;
UITabBarController *_tabBar;
LoginViewController *_loginvVewController;
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.loginvVewController = [[LoginViewController alloc] init];
// Add the tab bar controller's current view as a subview of the window
[self.window addSubview:self.loginvVewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)initializeTabbar {
/*
* Set up controllers for the tab bar controller
*/
EmployeeViewController *vc1 = [[[EmployeeViewController alloc] initWithTitle:#"View 1"] autorelease];
TaskViewController *vc2 = [[[TaskViewController alloc] initWithTitle:#"View 2"] autorelease];
HomeViewController *vc3 = [[[HomeViewController alloc] initWithTitle:#"View 3"] autorelease];
// View Controller with each Navigational stack support.
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:vc1];
/*
* Set up tab bar controller
*/
self.tabBar = [[UITabBarController alloc] init];
self.tabBar.viewControllers = [NSArray arrayWithObjects:navController, vc2, vc3, nil];
[self.window addSubview:self.tabBar.view];
}
In my quick hackathon for this problem, I have taken the button "Click here!" on login page - once you click on it will navigate you inside the app with tabbar. If you need the sample project then email me at d3minem#gmail.com.
After many requests via email - I have created the demo project and upload here. https://github.com/Deminem/SimpleTabbarApp--iPhone-
Please vote if you find it useful.
Good luck!
The better way would be to create a TabBarContoller based application and add the ViewControllers to the TabbarViewController.
The path is straight forward.
In IB, place your tabbar controller where you like it, make it have three pages and set their view controller classes.
Or in code, just add the tab bar controller with those three controllers set as its view controllers.
I have created a view based application and in the appdelegate .h file I have created UINavigationcontroller object and added it to window subview. Next in the app did finish launching I had allocated and initialised a class that I want to be viewed when the app first launches with the navigation bar on the top of it.
So this is the code I have did to add the class to navigation bar
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
[window addSubview:navController.view];
//test is the class that i want to be viewed first when the app launches first
test *t = [[test alloc]initWithNibName:#"test" bundle:nil];
[navController.view addSubview:t.view];
[window makeKeyAndVisible];
return YES;
}
but the problem is my test class launches but it does not display the navigation bar. What may be the problem?
Use some like this (add these lines)
appDelegate.h
UINavigationController *navController
#property (nonatomic,retain) UINavigationController *navController;
and in .m
test *t = [[test alloc]initWithNibName:#"test" bundle:nil];
self.navController=[[[UINavigationController alloc] initWithRootViewController:t] autorelease];
[window addSubview:self.navController.view];
[window makeKeyAndVisible];
it helps you.
From other view you need to make object of the appDelegate class then access the navigation controller of that class
see this
yourAppDelegateClass *objAppDelegate=(yourAppDelegateClass *)[[UIApplication sharedApplication] delegate];
now for pushing a view
SecondView *s=[[[SecondView alloc] initWithNibName:#"yournibName" bundle:nil] autorelease];
[objAppDelegate.navController pushViewController:s animated:YES];
this concept help you.
You shouldn't add your own view controller's view as a subview of the navigation controller. This way, you hide the navigation controller's view (including the navigation bar) and it makes the navigation controller pointless, because it doesn't know that your view controller wants to be part of its navigation stack.
Instead, push it on the navigation controller's stack by using:
[navController pushViewController:myViewController animated:NO];
Navigation bar is not coming because you are setting navigation controller's view to your test view. You can do it by setting navigation controller's view controllers which requires an array as -
test *t = [[test alloc]initWithNibName:#"test" bundle:nil];
NSArray *viewControllers = [[NSArray alloc] initWithObjects:t,nil];
[self.navigationController setViewControllers:viewControllers];
First, I don't see where you alloc init your navController. Secondly, you don't add a viewController to a navigation controllers view, rather you push the view controller onto the stack, like this:
[navController pushViewController:t animated:NO];
Hope this helps.
I am creating an application which I want to have a view controller with buttons as the first view controller with no navigation bar, and then when the user selects a button a table view controller appears managed by a navigation controller.
At the moment I am setting up the navigation controller in the app delegate and setting the top view controller as the table view controller I want to start the navigation bar on. So far I can see the navigation bar but that is it when I transition from the first view controller to the table view controller.
Any help would be much appreciated as I have confused myself with this issue.
I'm not totally clear on what you are asking, so I might have it wrong, but here goes.
The top navigation bar is can be displayed or hidden by calling:
self.navigationController.navigationBarHidden = NO;
In the viewWillAppear method of your viewController. So set it to YES or NO depending on whether or not you want it to be displayed.
#Disco, you would do something like so:
// In the App delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CustomViewController *viewController = [[CustomViewController alloc] init];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
// In your button method
- (IBAction)loadUpTableViewController:(id)sender {
CustomTableViewController *tvc = [[CustomTableViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:tvc];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[tvc release];
}