Is it possible to change/replace ViewContoller (and View) for one of the Tabs in a UITabBarController?
I would like to switch between 3 different ViewControllers in any order from a specific Tab (that´s why NavigationController is not possible).
They are set (in mass) using setViewControllers:animated: so you could do something like this.
// Assume tabController is the tab controller
// and newVC is the controller you want to be the new view controller at index 0
NSMutableArray *newControllers = [NSMutableArray arrayWithArray:tabController.viewControllers];
[newControllers replaceObjectAtIndex:0 withObject:newVC];
[tabController setViewControllers:newControllers animated:YES];
Hope that helps.
Related
I found this code here that i think will do the job.
`/* suppose we have a UITabBar *myBar, and an int index idx */
NSMutableArray modifyMe = [[myBar items] mutableCopy];
[modifyMe removeObjectAtIndex:idx];
NSArray *newItems = [[NSArray alloc] initWithArray:modifyMe];
[myBar setItems:newItems animated:true];`
The question is, where should i write this code in order to work?
I tried putting it in viewDidLoad of the UITabBarController but it didn't work.
If you're modifying the tabbar items from the UITabbarController, you can't use setItems:animated:. From the docs:
In iOS 3.0 and later, you should not attempt to use the methods and properties of this class to modify the tab bar when it is associated with a tab bar controller object. Modifying the tab bar in this way results in the throwing of an exception. Instead, any modifications to the tab bar or its items must occur through the tab bar controller interface.
Instead, swap out the viewControllers property of your UITabbarController, removing the UIViewController that corresponds to the tabbar item you want removed. For example, if you want to remove the 2nd tabbar item:
NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
[newViewControllers removeObjectAtIndex:1];
[self setViewControllers:newViewControllers];
I have a Tab bar Controller containing 5 Tabs and each tab bar item has individual navigation controller like :
Now , If i am currently in viewctrller3 of navigationctrller3 in Tab3 and i want to navigate to viewctrller2 of navigationctrller1 in Tab1 programmatically . Also I've selected the particular Tab1 programmatically But i m unable to reach viewctrller2 of
navigationctrller1. Is this feasible ?, If yes , then please elaborate..
Please guys join hands..!
If you are currently in viewctrller3, I think you should be able to do this:
UITabBarController *tabCont = (UITabBarController *)[self.navigationController parentViewController];
[tabCont setSelectedIndex:0];
UINavigationController *nav1 = tabCont.selectedViewController;
NSarray *newControllers = [NSArray arrayWithObjects:[nav1.viewControllers objectAtIndex:2],[nav1.viewControllers objectAtIndex:0],[nav1.viewControllers objectAtIndex:1], nil];
[nav1 setViewcontrollers:newControllers animated:NO];
That last line should rearrange the navigation controller's viewControllers so that viewctrller2 is now the top view controller.
One way to achieve this is
before setting the SelectedIndex of a tabbar , you maintain one reference variable in appDelegate and assign to it the name of the class which is required to be navigated after tab selection.
In the delegate of tabbar controller :
(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
check whether the visible controller is kind of class same as the class name that is set in appdelegate reference variable? If yes then nothing to do , if not then check if that controller is in the navigation stack or not? If its there in stack then pop/push to that index controller else create that controller and push to it.
I dont think that there will be any issue in this. suppose your nav1 is 1st navigationController.
[self.nav1 pushViewController:view2 animated:YES];
its will have to work for you.
From ViewController3 execute..
UINavigationController *navigationController1 = [appDelegate.tabBarController.viewControllers objectAtIndex:2]; // fetch the navigationController
[navigationController1 popToViewController:[navigationController1.viewControllers objectAtIndex:1] animated:NO];
[appDelegate .tabBarController setSelectedIndex:0];
I'm trying to select one of my UINavigationControllers in the UITabBar.viewControllers array.
I previously tried it with setting the UITabbarController.selectedIndex, but the Apple documentation says:
"To select the More navigation controller itself, you must change the value of the selectedViewController property instead."
AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
UINavigationController *navController = [appDelegate.objTabBarController.viewControllers objectAtIndex:5];
[appDelegate.objTabBarController setSelectedViewController:navController];
Doing so is fine but when I change back to the MoreViewController's list view, the icon on the left side is gone and won't come back.
Everything ok, when selecting it with the finger.
Bug when selecting programmatically -> image is gone
Any suggestions what I'm doing wrong?
Best regards,
Steve
Selecting the More Navigation Controller
To select the moreNavigationController, you must set the selectedViewController:
self.tabBarController.selectedViewController = self.tabBarController.moreNavigationController;
The reason for that is simple: The moreNavigationController is not inside the viewControllers of the tab bar controller, so it can't be selected by index.
To select one of the "more" controllers directly, you can either set the selectedViewController property:
self.tabBarController.selectedViewController = viewController5;
Or you can set the selectedIndex:
self.tabBarController.selectedIndex = 5;
Fixing the Disappearing Tab Bar Image
The disappearing tab bar image is caused by using a navigation controller (for the settings) inside a navigation controller (the moreNavigationController generated by the tab bar controller). To fix it, there are two solutions:
Don't add navigation controllers for the more section, but add the controllers directly. The controller structure would look like this, assuming the controllers in all tabs need navigation:
tabBarController
+ navigationController
+ viewController0
+ navigationController
+ viewController1
+ navigationController
+ viewController2
+ navigationController
+ viewController3
+ viewController4
+ viewController5
Set the tabBarItem of the settings controller on its navigation controller (you only need to do this once):
UINavigationController *settingsNavigationController = [appDelegate.objTabBarController objectAtIndex:5];
UIViewController *settingsRootController = settingsNavigationController.viewControllers[0];
settingsNavigationController.tabBarItem = settingsRootController.tabBarItem;
I ran into this same problem. It seems that the navigation controller was somehow losing track of the view controller. In my case, the navigation controller whose image was disappearing was at index 7 in the tabBarController. The navigation controller was supposed to contain a viewController of class SettingsViewController. But sometimes it lost it.
To fix it, I had to add code to two classes -- the app delegate and SettingsViewController. In the app delegate:
-(void) fixSettingsNavigationController {
UITabBarController* tab = self.tabBarController;
NSArray* vcs = tab.viewControllers;
NSInteger nVCs = vcs.count;
if (nVCs > 7) {
UIViewController* settingsContainer = vcs[7];
UINavigationController* settingsContainerNav = (UINavigationController*)settingsContainer;
if ([settingsContainerNav isKindOfClass: [UINavigationController class]]) {
NSArray* settingsNavVCs = settingsContainerNav.viewControllers;
NSInteger count = settingsNavVCs.count;
SettingsViewController* svc = self.settingsViewController;
if (!count) {
// The container navigation controller has lost track of the settings view controller.
settingsContainerNav.viewControllers = [NSArray arrayWithObject:svc];
}
}
}
}
And in SettingsViewController:
-(void) viewWillDisappear:(BOOL)animated {
MyAppDelegate* appDel = [[UIApplication sharedApplication] delegate];
[appDel fixSettingsNavigationController];
[super viewWillDisappear: animated];
}
I ran to the very similar situation, where I want to select a View controller inside MoreViewController programmatically.
As you said in your question, apple don't allow selecting a view controller that is inside MoreViewController (Or not visible in tabbar).
In my case, I don't need default "More" features of reordering tabs in tabbar.
So, I did following things
Created a UITableViewControlelr as my 5th tab, set its Title to more and custom image (Similar to default more image).
In my UITableViewController I listed items that corresponds to ViewControllers. Tapping on which show respective view controller.
When i need to show any view controller that is inside my UITableViewController programatically, i simply set a flag and push my UITableViewController, and in viewDidAppear method of my UITableViewController push desired view controller.
This will also show back button on programatically opened view to list of MoreViewController
I have a nib with four UIViewControllers each with a UITabBarItem. At runtime, based on user options, I need to show or hide one of the UITabBarItems. I cannot figure out how to remove the UITabBatItem.
Does anyone know how to do this?
Thanks
Christian's code is close. It should be:
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:myTabBarController.viewControllers];
[viewControllers removeObjectAtIndex:indexToRemove];
[myTabBarController setViewControllers:viewControllers];
To remove one, you can just get the viewControllers from the TabBar and put them in an NSMutableArray. Then remove the index you want removed and then set the viewControllers property to this new array of view controllers using
setViewControllers:animated:
Hoep this helps.
Get the tab bar controller's view controllers, remove the one you want to 'hide' and then set the tab bar controller's viewControllers array to this new array.
NSMutableArray *viewControllers = [myTabBarController viewControllers];
[viewControllers removeObjectAtIndex:indexToRemove];
[myTabBarController setViewControllers:viewControllers animated:YES];
I would like for one tab in a UITabBarController to have a fixed position and the user can reorganize the other tabs however they like. I have the UITabBarController > UINavigationController > UITableViewController setup.
Is this possible?
UPDATE:
The following code, in applicationDidFinishLaunching, is what I'm using and it doesn't work. I'm trying to get a reference to the SavedTableViewController, I think that's the problem. Any ideas?
NSMutableArray *customizableVCs = [NSMutableArray arrayWithArray:tabBarController.customizableViewControllers];
for (id controller in tabBarController.customizableViewControllers){
if ([controller isKindOfClass:[SavedTableViewController class]]){
NSLog(#"Removing Object");
[customizableVCs removeObject:controller];
}
}
tabBarController.customizableViewControllers = customizableVCs;
UPDATE 2:
This is the code that worked for me. I had to put the snippet below adding the tabBarController to the window.
[window addSubview:tabBarController.view];
[self setTabOrderIfSaved];
NSMutableArray *customizableViewControllers = [NSMutableArray arrayWithArray:tabBarController.customizableViewControllers];
[customizableViewControllers removeObject:savedNavigationController];
tabBarController.customizableViewControllers = customizableViewControllers;
Remove the view controller corresponding to that tab from the customizableViewControllers property of your tab bar controller. Assuming that you want fixedViewController to remain fixed:
NSMutableArray *customizableViewControllers = [NSMutableArray arrayWithArray:tabBarController.customizableViewControllers];
[customizableViewControllers removeObject:fixedViewController];
tabBarController.customizableViewControllers = customizableViewControllers;
Because customizableViewControllers is reinitialized when the viewControllers property is changed, you should do this after the rest of your tab bar controller’s state has been set up.