I have created a .xib file containing a UITabBar with 5 UITabBarItems inside. I would like 4 of the 5 tabs to link to the same UIViewController class since they have the exact same interface (only the data differentiate their looks).
Therefore it makes sense for me to instantiate my UIViewController 4 times, once per tab bar item. And then link each one of the UITabBarItems of the .xib with one instance of my UIViewController.
But I cannot figure out a way to take a reference of my xib tab bar items in my UIViewController and send the setTabBarItem message. How could I achieve that ? I was trying somehow to pass the .xib tab bar items on init (overwriting the init) but I didn't manage to reference them. I instantiate the controllers in the AppDelegate after the self.window stuff.
(If I say something weird here, not making sense with the usual iOS programming conventions, please let me know)
Use UITabBarController for this , not sure what you exactly want to do with the same UIViewController but UITabbarController will definitely work;
UITabBarController *tabBarController = [[[UITabBarController alloc] init] autorelease];
ViewController *viewController1 = [[ViewController alloc]initWithNibName:#"ViewController1"];
ViewController2 *viewController2 = [[ViewController2 alloc]initWithNibName:#"ViewController2"];
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1,viewController1,viewController1,viewController1,viewController2,nil];
self.window.rootViewController = tabBarController;
Related
I've heard Facebook and Google do not use UIStoryboards or nibs because they are difficult to merge – they format all their views programmatically. Are there any resources out there that can provide some guidance as to how best to position assets, handle localization, organize files, etc., when creating all your views without nibs?
The first step would be to create an UINavigationController or a UITabBarController within the AppDelegate's didFinishLaunching method, where you should set the rootViewController for the current UIWindow ([window setRootViewController:]).
Then you just have to create your content viewcontrollers and views. Let's say you want to create a menu, then you should create a MneuViewController which inherits from UIViewController and a MenuView which inherits from UIView. Within the MenuView code you create your view components like labels, textfields or whatever you need. In the MenuViewController you create an instance of the MenuView class and call [self setView:] with that object. Finally you have to add the ViewControllers to your rootViewController.
The AppDelegate should look similar to something like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MenuViewController *mvc = [[MenuViewController alloc] init];
UINavigationController *rootViewController = [[UINavigationController alloc] initWithRootViewController: mvc];
[self.window setRootViewController: rootViewController];
[self.window makeKeyAndVisible];
}
Localization has to be done using the macro NSLocalizedString() for which you should find a lot of samples.
Files should be handled using NSFileManager.
For eveything else you should ask more specific questions.
I'm searching for a solution to split Storyboard at UITabBar level.
I have an app with 5 tab and i want to manage every single tab with a different storyboard.
The structure would be a simple minimal storyboard with the tab bar controller and 5 bigger storyboards with every tab viewcontrollers (and segues) which must inherit the tab bar.
Does everyone ever splitted the storyboard like this ? Any clue?
Thanks
I think it could be possible, this should go in "viewDidLoad" of your custom UITabBarController...
NSMutableArray *controllersArray = [[NSMutableArray alloc] init];
// Load the initial UIViewController from every Storyboard
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Storyboard1" bundle:nil];
UIViewController *first = [sb instantiateViewControllerWithIdentifier:#"firstViewController"];
[controllersArray addObject:first];
// Repeat the process with the rest
...
// Set your controllers
self.viewControllers = [controllersArray copy];
Remember to set an Storyboard ID for every main UIViewController, in the example is 'firstViewController'.
we used RBStoryboardLink from: http://robsprogramknowledge.blogspot.co.il/search/label/UIStoryboard
to solve this issue
I am using iOS 5.1 and I need to create a Custom TabBar for my app. When app will be launched, the control will be pushed to the Custom TabbBar Controller class. Here is what I am doing. I have created class derived from UITabBarController and I used XIB also. In the XIB, I can see the UIView Objetc containing the Tab Bar and when I am adding more Tabs in that tabBar, it is not reflecting when I run the App and I can see only One Black TabBar without any title and color. I remember earlier we use the MainWindow.xib to add the TabBarController and for each TabBar Item we add the Navigation Controller so that every tab has its own Navigation controller but I am not getting how it can be done if I have used the XIB derived from UiTabBarController Class.Please let me know if I am unclear at any point. I will give more clarification. All I want to know why the changes on the TabBar of the XIB are not reflecting in the app?
The lower image showing the XIB and App so you can see that I have added the Four Tabs in the UITabBar but in the app there is only one Black Bar.
From the Apple Documentation about UITabBarController:
This class is not intended for subclassing. Instead, you use instances of it as-is to present an interface that allows the user to choose between different modes of operation
You can't subclass it. If the original UITabBarController doesn't have the features you are looking for, your only choice is to create a new custom tab bar controller without subclassing the original one.
EDIT: not sure if you want to do this. Are you simply trying to load an UITabBarController from a nib? If so, subclassing is not necessary. It would be better to use storyboards ;-) but you can do it even with nib.
You have to simply do this:
1- add an empty xib to the project and call it TabBar (only xib. No source files)
2- put an UITabBarController inside that nib. No other components, only that UITabBarController
3- put this code in the AppDelegate application didFinishLaunchingWithOptions method:
// this code should be already in that method if you have used the empty application model
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// this is the new code to add. You are programmatically loading an instance of UITabBarController from the nib named TabBar.xib
UITabBarController *tb = (UITabBarController *)[[[NSBundle mainBundle]loadNibNamed:#"TabBar" owner:self options:nil] objectAtIndex:0];
// here you are assigning the tb as the root viewcontroller
self.window.rootViewController = tb;
// this code is standard in this method
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
Then you can customize your UITabBarController and it should load correctly.
Take care: if you add other objects inside the nib, you must change the line
UITabBarController *tb = (UITabBarController *)[[[NSBundle mainBundle]loadNibNamed:#"TabBar" owner:self options:nil] objectAtIndex:0];
with a loop and some check to see if you are really loading the UITabBarController and not other components. Now I'm simply loading the first object in the nib, without taking care if it's a UITabBarController or an UIPotato ;-)
I read that it is bad to have such structure in an iOS application. But what if an application has a lot of UINavigationControllers and UITabBarControllers. But one UINavigationBar and one UITabBar are always displayed only? Other UINavigationBars and UITabBars are hidden.
EDITED
For example, in navigation-based application I call this code:
- (IBAction)openTabsController:(id)sender {
tabOneController *tabOneViewContr = [[[tabOneController alloc] initWithNibName:#"tabOneController" bundle:nil] autorelease];
UINavigationController *tabOneNavContr = [[UINavigationController alloc] initWithRootViewController:tabOneViewContr];
tabTwoController *tabTwoViewContr = [[[tabTwoController alloc] initWithNibName:#"tabTwoController" bundle:nil] autorelease];
UINavigationController *tabTwoNavContr = [[UINavigationController alloc] initWithRootViewController:tabTwoViewContr];
UITabBarController *tabContr = [[[UITabBarController alloc] init] autorelease];
tabContr.viewControllers = [NSArray arrayWithObjects:tabOneNavContr,tabTwoNavContr, nil];
sel.navigationController.navigationBar.hidden = YES;
[self.navigationController pushViewController:tabContr animated:YES];
}
After calling of this method I have two UINavigationControllers and one UITabBarController. At the same time I have one UINavigationBar and one UITabBar on a screen.
EDITED
Approximate scheme.
From The beginning we have an UINavigationController which allows to navigate between the views (circles). Then after pushing an UITabBar appears and allows to switch between the views. A rectangle with two little rects is a view with a UITabBar with 2 UITabBarItem s. When we presss any UITabBarItem another UIView appears. In this UIView we can press some button which calls another view with another UITabBar. Current UITabBar is visible after pushing if it is not hidden with another UITabBar.
is it more clear now?
The code above works almost perfect (except of some animations and not including Apple's limitations)
Gargo,
I'm not sure I understood your question but the apple documentation is clear. If you use - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated it says that viewController:
cannot be an instance of tab bar controller and it must not already be
on the navigation stack.
Since you do
[self.navigationController pushViewController:tabContr animated:YES];
you are pushing a tab bar controller instance within the navigation stack.
If you add the structure that you would achieve maybe I can help you to find another solution.
Hope that helps.
An app should only have one working tabBarController at any one time.
A tabBarController should also be the root view controller. Always. (If you need a login view or similar before the tabBarController, then remove the login view, create the tabBarController and then make that the root).
This is Apple' advice spoken to me personally by Apple engineers.
Remember, apps should be small applications that are quick and easy to use/navigate. If you feel the need for more than one tabBarController then your app design is likely very wrong from a UI/Usability perspective.
I have an application that has a UITabBarController created in IB. That tbc loads 3 views which work fine up to now.
I decided to INSERT a UINavController as the starting VC and have a UITableViewController display 4 menu items in cells. Each of the 4 items will in essence load the UITabBarController put pass in a different xml file to process in order to display data in those 3 tabs.
I essentially did this at the end of the applicationDidFinishLoading:
MainMenu *rootViewController = [[MainMenu alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navController;
[window makeKeyAndVisible];
return YES;
I then created the MainMenu as the rootViewController subclassing UITableViewController and added a hardcoded array for now which displays the 4 items I want. I had the didSelectRowAtIndexPath run this code:
tabBarController = [[UITabBarController alloc] init];
[self.navigationController pushViewController:tabBarController animated:YES];
[tabBarController release];
It turns out that when I run it, the navcontroller pushes the tab controller but only the first tab shows up. Here is a pic.
You should never push a UITabBarController from a UINavigationController. Apple clearly says this:
An app that uses a tab bar controller can also use navigation controllers in one or more tabs. When combining these two types of view controller in the same user interface, the tab bar controller always acts as the wrapper for the navigation controllers.`
That essentially means tab bar should be the parent of all other view controllers that get called. Not the other way round. You should probably change the way you present your app.
More information here.