Displaying an UIViewController that is not present in UITabBarController's controller list - iphone

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...)

Related

iOS - is it possible to select view for a uitabbar at runtime?

I am assigning my view controller to my tab right after I create it. Is it possible to select the view that will show after the tab is clicked?
For eg
//user clicks tab 1
if(hasMessages)
//show view A
else
//show view B
Yes, it is possible. You need to set a delegate for your tab controller:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
tabBarController.delegate = self; // or whatever suitable class you have
This delegate needs to conform to the UITabBarControllerDelegate protocol.
In your delegate, implement tabBarController:didSelectViewController: and inside it, find out which view you want to present. Assuming your tab's root view controller is a navigation controller, then the delegate method implementation would be something like this:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
/* logic goes here */
[viewController pushViewController:someNewVC animated:YES];
}

select Tab Bar button

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

Selected index on the "more" view of a UITabbar

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.

Disable tab bar navigating to root view

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

Problem popping to root nav controller on tab bar switch

Trying to mimic/copy the built-in address book, specifically the behavior when editing a contact or viewing an existing contact's Info from inside the Phone app. When you navigate to another tab, the editing state is reset and the "New Contact" or "Info" view is popped so that when you come back to the Contacts tab, you are back at the root table view.
I have most of this working inside viewWillDisappear using setEditing: and popToViewController: however I get strange behavior when the user navigates from the Info view to the table view using the back button. Even if I pop to the root table view controller, it seems to be using the default UITableViewController class and not my subclass (e.g. standard selection behaviors instead of my overrides to push the detail view.)
Any hints? IPD
Here's some code to illustrate:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// This is to clean up from the colored bar in detail view
self.navigationController.navigationBar.tintColor = nil;
// These are to match the behaviour of Contacts app
[self setEditing:NO animated:NO];
// This is the tricky part: works when switching tabs, but not when back button was going to pop anyway!!
[self.navigationController popToViewController:rootViewControllerForTab animated:NO];
}
The -viewWillDisappear: method is not the best place for modifying the view controller stack for your navigationController because it is triggered both when you switch tabs and when a view is pushed on top of it.
I played around with this a bit and found that the best place for this is in the -[UITabBarControllerDelegate tabBarController:didSelectViewController:] method. So, first you need to designate an object to be the delegate for your tab bar (I used the app delegate). Bind the delegate property of your UITabBarController to an object implementing the UITabBarControllerDelegate protocol in code or in Interface Builder.
Then, implement the -tabBarController:didSelectViewController: method. The trick now is how to tell when your "address book" tab is being switched to. I kept track of the view controller for the tab in question using a property of type UINavigationController (the root view controller for the tab). After binding the tab1NavController property to the actual instance using Interface Builder, it can be used to compare to the viewController parameter to see what tab was just selected.
#interface Pop2RootTabSwitchAppDelegate : NSObject
<UIApplicationDelegate, UITabBarControllerDelegate> {
UINavigationController *tab1NavController;
}
#property (nonatomic, retain) IBOutlet UINavigationController *tab1NavController;
#end
#implementation Pop2RootTabSwitchAppDelegate
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController {
NSLog(#"[%# tabBarController:%# didSelectViewController:%#]", [self class],
tabBarController, viewController);
if (viewController == tab1NavController) {
NSLog(#"viewController == tab1NavController");
[tab1NavController popToRootViewControllerAnimated:NO];
}
}