I am programmatically changing the tab bar item for my tab bar at runtime.
The whole UI of my app uses Storyboards and this is the only area where I am making the UI changes in code.
So, the UI changes depending on a property. If this property cannot be found, the array of viewControllers changes to the new array that contains the new UIView.
Here's my code for the TabBarController.m:
NSArray *arrayOfControllers = self.viewControllers;
NSMutableArray *newArrayOfControllers = [[NSMutableArray alloc]init];
for (id controller in arrayOfControllers)
{
[newArrayOfControllers addObject:controller];
}
if ( !isMember)
{
NotMemberVC *vc = [[NotMemberVC alloc]init];
vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Test" image:[UIImage imageNamed:#"door-sign.png"] tag:0];
[newArrayOfControllers removeLastObject];
[newArrayOfControllers addObject:vc];
self.viewControllers = newArrayOfControllers;
}
And here's what it looks like when I select this new tab bar item:
Any suggestions as to how I can fix this?
First of all you don't need to do a for cycle when you have a method to do a mutableCopy of the array:
NSArray *arrayOfControllers = self.viewControllers;
NSMutableArray *newArrayOfControllers = [arrayOfControllers mutableCopy];
then here, you was not initializating the viewController with the view. In this case you have your VC with the UIView in your storyboard, and so you have to choose a StoryboardID in your VC in the Storyboard, and then:
if ( !isMember)
{
NotMemberVC *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"Your_Identifier_ViewController_Storyboard"];
vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Test" image:[UIImage imageNamed:#"door-sign.png"] tag:0];
[newArrayOfControllers removeLastObject];
[newArrayOfControllers addObject:vc];
//Here make a copy to come back to immutable array
self.viewControllers = [newArrayOfControllers copy];
}
Related
In Tab bar Controller, Initially I had added 3 tab bar items in it.After successful login, I need to add one more item dynamically in my current Tab bar Controller . Is it possible to add dynamically ? Below is the code i have tried but its not working.
if (AppContext.loginUser.userId!=nil) {
UITabBarItem *tabBarItem4;// = [tabBar.items objectAtIndex:3];
tabBarItem4.selectedImage = [[UIImage imageNamed:#"SelectedProfileTab"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal ];
tabBarItem4.image = [[UIImage imageNamed:#"Profiletab"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal ];
tabBarItem4.title = #"Profile";
tabBarItem4.tag =4;
ProfileVC *profile = loadViewController(TabbarSB, VC_Profile);
UINavigationController *nv=[[UINavigationController alloc] initWithRootViewController:profile];
NSMutableArray *arrayOfTabBars=[AppContext.mainTabbar.viewControllers mutableCopy];
[arrayOfTabBars addObject:nv];
// [AppContext.mainTabbar setViewControllers:nil];
[AppContext.mainTabbar setViewControllers:arrayOfTabBars];
//AppContext.mainTabbar.viewControllers = arrayOfTabBars;
// [self.tabBarController.tabBarController addChildViewController:profile];
}
You can do that programmatically:
if (AppContext.loginUser.userId!=nil) {
// First, create your view controller
ProfileVC *profile = loadViewController(TabbarSB, VC_Profile);
// then embed it to a navigation controller
// this is not required, only if you need it
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:profile];
// Get viewControllers array and add navigation controller
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
[viewControllers addObject:nav];
// Set back the array
[self.tabBarController setViewControllers:viewControllers];
// Create tab bar item for ProfileVC
profile.tabBarItem = [[UITabBarItem alloc] initWithTitle:title image:image selectedImage:selectedImage];
}
I have a view controller say 'HomeViewController' on which I have added a UITabBarController, which has 4 UITabBarItems. Now what I want is, when I select the HomeViewController no tab should should be selected for the first time and another view should be loaded. I have tried UITabBar instead of UITabBarController but its not working. I have also tried :
tabBarController.selectedViewController=nil; //giving crash
tabBarController.selectedIndex=-1; //not working either
UITabBarItems should be selected when user will click on them.
You have to add UITabBar object on HomeViewController.
In ViewDidLoad you have to add following code:
ViewController1 *controller1 = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil];
ViewController2 *controller2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
viewControllersArray = [[NSArray alloc] initWithObjects:controller1,controller2, nil];
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [[NSArray alloc] initWithArray:viewControllersArray];
for(int i = 0; i < tabBarController.tabBar.items.count; i++){
[[tabBarController.tabBar.items objectAtIndex:i] setTitle:[[tabBar.items objectAtIndex:i] title]];
}
isItemSelected = NO;
Also set the tag of tab bar items starting from 0. As 0 for first item, 1 for second item and so on.
and implement delegate method:
(void)tabBar:(UITabBar *)tabBar1 didSelectItem:(UITabBarItem *)item{
if(!isItemSelected){
isItemSelected = YES;
AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDel.window.rootViewController = tabBarController;
}
tabBarController.selectedIndex = item.tag;
tabBarController.selectedViewController = [viewControllersArray objectAtIndex:item.tag];
}
I think this is not the right way, as Concept of creating TabBar says that " Show the particular controller of related tab". If u do not select any tab than what else you will show on screen, "A black screen ?". so please re-architecture your design.
After pushing a ViewController using this code
UIViewController *vc = [[self storyboard] instantiateViewControllerWithIdentifier:#"frontCardViewController"];
[self.navigationController pushViewController:vc animated:YES];
I remove all ViewControllers I don't need anymore using this code
NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray:self.navigationController.viewControllers];
NSArray *array = [[NSArray alloc] initWithArray:navigationArray];
for (UIViewController *viewController in array) {
if ([viewController isKindOfClass:[RITCardViewController class]]) {
RSLog(#"Is kind of Class RITCardViewController");
[navigationArray removeObject:viewController];
}
}
self.navigationController.viewControllers = navigationArray;
The navigation array now looks like this:
"RITMainViewController: 0x10d81fc1>",
"RITDetailViewController: 0x10d847880",
"RITTestResultViewController: 0x113d0e090"
But the problem is that if the back button in the navigation bar is pressed now, it goes back to the second screen. But when the back button is pressed again it just stays on this screen. It seems to go trough all the screens I have removed, but doesn't show them.
What am I doing wrong?
Try something like this instead:
NSMutableArray *viewControllers = [#[] mutableCopy];
for (UIViewController *vc in self.nagivationController.viewControllers)
{
if (NO == [vc isKindOfClass:[RITCardViewController class]])
[viewControllers addObject:vc];
}
self.navigationController.viewControllers = viewControllers;
Make sure you don't corrupt the stack by removing the view controller you are currently on from the view controllers array. Assuming your current view controller is not an instance of RITCardViewController you should be fine. Otherwise, you'll have to make up for it in your code.
I have an app with an "old" Tabbarcontroller and a MainWindow.xib. I have to delete the tabbarcontroller logic to transform the app and made a "Left side menu" type, like facebook. I have a problem, i have alredy created the left side menĂ¹ with a tableviewcontroller and i can open,close and push correctly my controllers... Now i want to insert a different customnavigation bar class each navigation controller (in the old version of the app each navigation controller had his custom navigation class to change che image in relation with the active viewcontroller). This is the code i use in the tableview didselect method of a row in my left side menu:
if (indexPath.row==1) {
DemoViewController *demoController = [[DemoViewController alloc] init];
UINavigationController *navigationController = self.menuContainerViewController.centerViewController;
[navigationController setValue:[[CustomNavigationBar alloc]init] forKeyPath:#"navigationBar"];
NSArray *controllers = [NSArray arrayWithObject:demoController];
navigationController.viewControllers = controllers;
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];
}
this code manage correctly the slide and load correctly the viewcontroller inside MFSideMenu. The custom navigationbar class is assigned but not works correctly:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
this method is never called, maybe MFSideMenu overwrites the uinavigationcontroller delegate? How i can do to made "active" again this navigation controller delegate method?
found a solution,this code:
DemoViewController *demoController = [[DemoViewController alloc] init];
UINavigationController *navigationController = self.menuContainerViewController.centerViewController;
CustomNavigationBar *navClass=[[CustomNavigationBar alloc]init];
[navigationController setValue:navClass forKeyPath:#"navigationBar"];
[navigationController setDelegate:navClass];
NSArray *controllers = [NSArray arrayWithObject:demoController];
navigationController.viewControllers = controllers;
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];
instead of:
DemoViewController *demoController = [[DemoViewController alloc] init];
UINavigationController *navigationController = self.menuContainerViewController.centerViewController;
[navigationController setValue:[[CustomNavigationBar alloc]init] forKeyPath:#"navigationBar"];
NSArray *controllers = [NSArray arrayWithObject:demoController];
navigationController.viewControllers = controllers;
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];
In this way the delegate is assigned correctly...
I had a navigation controller based application. And I decided to use tab bars in my application.
When the user presses at a certain tab bar item I want to display a certain view controller - and I want programmatically in my code choose which one to display.
I tried to add in the Interface Builder a navigation controller into my tab bar, but viewWillAppear of its view controller is not being called.
How can I implement this feature?
I don't know if it's the "right way", but here's how I usually do this with three tabs.
- (void)initControls {
// Create the window.
[self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
// Create Tab Bar.
tabCon = [[UITabBarController alloc] init];
// Local array variable that holds the viewcontrollers.
// Capacity corresponds to the number of VC's
NSMutableArray *localVCArray = [[NSMutableArray alloc] initWithCapacity:3];
MyFirstViewController *oneViewController = [[MyFirstViewController alloc] init];
UINavigationController *oneNavCon = [[UINavigationController alloc] initWithRootViewController:oneViewController];
[localVCArray addObject:oneNavCon];
[oneViewController release];
[oneNavCon release];
MySecondViewController *twoViewController = [[MySecondViewController alloc] init];
UINavigationController *twoNavCon = [[UINavigationController alloc] initWithRootViewController:twoViewController];
[localVCArray addObject:twoNavCon];
[twoViewController release];
[twoNavCon release];
MyThirdViewController *threeViewController = [[MyThirdViewController alloc] init];
UINavigationController *threeNavCon = [[UINavigationController alloc] initWithRootViewController:threeViewController];
[localVCArray addObject:threeNavCon];
[threeViewController release];
[threeNavCon release];
// Set the tab bars array of view controllers to the localVCArray
[[self tabCon] setViewControllers:localVCArray animated:YES];
// Release the localVCArray, all of its contents are now retained by tabCon.
[localVCArray release];
// Add controls to window and show.
[window addSubview:[tabCon view]];
[window makeKeyAndVisible];
}
In the init method each viewController you can do something like:
[[self tabBarItem] setImage:[dataSource tabConImg]];
[[self tabBarItem] setTitle:[dataSource name]];
[[self navigationItem] setTitle:[dataSource navConName]];
To set the icon used in the tab bar, the title in the tab bar, and the title of you navigation item.