I have a tab bar based application with navigation on each tab bar item.
When i navigate to another view on any tab bar item and click on on tab bar item,then root view controller on that tab bar item is called.
Its like PopToRootView .
Can we disable this situation?
Yes, you can disable the automatic popToRootViewController by implementing the UITabBarControllerDelegate method on your view controller:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if(self.navigationController == viewController) {
return NO;
}
return YES;
}
Thanks to: Disable action - user taps on tabbar item to go to root view controller
Though they say you're not supposed to subclass UINavigationController, you can what you want by making a subclass of UINavigationController and overriding the - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated; method.
Doing this (and not calling the super popToRootViewController) will prevent the view controllers from popping when you click the tab bar item. It could run you into some problems somehow, but hopefully it works for you.
Include UITabBarControllerDelegate in your header file.
try this:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
if(bool_youDontWantPopToRootView)
return (tabBarController.selectedViewController != viewController);
return YES;
}
For bool_youDontWantPopToRootView, you can add condition into it when you want it to behave like default behaviour.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated; when you pass 'NO' in animated argument you will be directed to root view without any animation
you dont need to use this method while you tap on any tab bar its the default behaviour of the navigation controller that it maintain its own stack of VCs
Related
Let me give an example what about what I want to do:
I have a tab that has 4 TabBarItems, so it contains 4 controllers. And there is a controller that must not get shown up in tab bar's icons, but it will get shown when a button inside one of these 4 controllers are touched. So when it get's shown, the tabbar must not have any selected tabs, every item must be deselected. It must be like a ghost controller that is not shown in tab icons but it's actually a controller that's in tab bar controller.
What's the best way to achieve this? Fyi, I don't want a modal dialog, the tabbar must always be visible underneath.
One thing which might help is knowing when a transition between tabs is happening. If you display your ghost view as soon as the transition happens, you might have enough control to do what you want.
Here's how I do that: first, sub-class UITabBarController to TabViewController (for example). In your TabViewController, include this method:
// Pass this message on to views so they know when transitions are occuring
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
UIViewController <UITabBarControllerDelegate> *obj;
for ( obj in self.viewControllers ) {
if ( [obj respondsToSelector:_cmd] ) {
[obj tabBarController:tabBarController didSelectViewController:viewController];
}
}
}
Set each of your tabbed view classes to adopt the UITabBarControllerDelegate protocol. Then, include a method like this in each class to "intercept" the transition events:
// This is called when a transition between tabs happens
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
if ( [viewController isEqual:self] ) {
// Transitioning to me
// Do stuff
}
else {
// Transitioning to someone else
// Do stuff
}
}
(note: there might be cleaner ways of implementing this, but it's been working fine for me...)
I want to hide an image when the tabBar button is pressed.I have
self.tabBarController.delegate = self;
in my app delegate and the code below is located in my view controller's .m file . but it doesn't work . Can anyone help pls ?
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
if (viewController.tabBarController == nil)
{
img.hidden = YES;
NSLog(#"Tab Bar Button");
}
}
Do you know that
In versions of iOS prior to version
3.0, this method is called only when the selected view controller actually
changes. In other words, it is not
called when the same view controller
is selected.
In addition to this, make sure you are hiding the imageView that contains the image.
UPDATE
Get the tabBarController instance in the view controller and make its delegate the view controller. Then you can call this method in the view controller.
give name for the tabbarcontroller and then set the delegate for that.If my suggestion not useful,then ask me freely
How can I manage the user selection on the "more" view of a UITabBar? I have this code to manage the UITabBarItems selections:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
if (!(viewController == tabBarController.moreNavigationController)) {
int index = tabBarController.selectedIndex;
[[DataManager sharedInstance] setCurrentTabbarIndex:index];
}
}
It works fine for the visible UITabBarItems, but when the user select some item from the "more" view I never get informed about that. Is there some way to catch the user item selection of the "more" view? Thanks!
The "more" view of a UITabBarController is handled separately from the other views. Apple's discussion on this subject says the following:
[The 'moreNavigationController'] property always contains a valid More navigation controller, even if a More button is not displayed on the screen. You can use the value of this property to select the More navigation controller in the tab bar interface or to compare it against the currently selected view controller.
Do not add the object stored in this property to your tab bar interface manually. The More controller is displayed automatically by the tab bar controller as it is needed. You must also not look for the More navigation controller in the array of view controllers stored in the viewControllers property. The tab bar controller does not include the More navigation controller in that array of objects.
Judging from that I would think that you can do something like:
int index = tabBarController.selectedIndex;
if (tabBarController.selectedViewController ==
tabBarController.moreNavigationController) {
index = -1; //assign some placeholder index for the "More" controller
}
A very late answer for a very old question, but here it is anyway, in case someone stumbles upon this.
The solution is to assign yourself as the delegate of the "more" navigation controller. You already have a class that adopts the UITabBarControllerDelegate protocol, so the .h file might look like this:
#interface MyDelegate : NSObject <UITabBarControllerDelegate, UINavigationControllerDelegate>
{
}
Wherever you are assigning your class as delegate, do this:
- (void) assignDelegate:(MyDelegate)myDelegate toTabBarController:(UITabBarController*)tabBarController
{
tabBarController.delegate = myDelegate;
tabBarController.moreNavigationController.delegate = myDelegate;
}
And finally, in your delegate class add this method:
- (void) navigationController:(UINavigationController*)navigationController didShowViewController:(UIViewController*)viewController animated:(BOOL)animated
{
// add code to handle the event
}
Note that none of your delegate methods are invoked when you change tabs programmatically.
The best approach I've found for this problem is to become the delegate for the UITableView which is the topViewController in the UITabBarController.moreViewController.
Implementing the didSelectRowAtIndexPath should solve the problem!
The best (and most secure) implementation for this is described by Stuart Sharpe in his blog: http://initwithstyle.net/2014/02/making-more-of-the-more-view/
Whatever view is being selected will receive viewWillAppear:animated:
Provide this in every view that's controlled by your tab bar, and you can thus extract the identity of the user's selection even when made from a "More" controller.
You can save the tab bar state right in this method, or you can provide your views with a reference back to the tab bar and notify it.
I want to disable the default action when user taps the tabbar item.
For example, i have a tabbar with Tab1, Tab2 and Tab3. In Tab1, user can navigate from View1 to View3 (View1 > View2 > View3). If user is at View3, and he taps the Tab1, the application takes the user to View1 (the root view controller). I want to disable this functionality. I don't want the tap on Tab1 to pop all the view controllers. How can i do that?
Edit:
This behavior is a little strange, but a handy shortcut in case of deep hierarchy!
You can implement following UITabBarControllerDelegate methods to disable this system wide shortcut:
#pragma mark -
#pragma mark UITabBarControllerDelegate
- (BOOL)tabBarController:(UITabBarController *)tbc shouldSelectViewController:(UIViewController *)vc {
UIViewController *tbSelectedController = tbc.selectedViewController;
if ([tbSelectedController isEqual:vc]) {
return NO;
}
return YES;
}
if you look at the UITabBarController delegate there is a method:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
If you implement this in your class, you can check if the UIViewController is the already displayed one and then return NO, which will stop this from happening.
I had the same problem with a ABPeoplePicker object embedded in a UITabBarController, in that pressing the 'Contacts' tab a second time which was already displayed would make the ABPeoplePicker control show the 'Groups'
HI,
i have added the following in Appdelegate.m file to hide particular tab bar item("Hai") in tab bar controller(created by IB).but it did not work
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if ([viewController.tabBarItem.title isEqualToString:#"Hai"])
{
self.tabBarController.tabBar.hidden = YES;
}
}
There is no way to hide a tab bar item, but you could create an array of view controllers and exclude this particular one from that array. Later when the tab should be visible, set the view controllers for the tab bar controller again and include that view controller this time.
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated