UITabBarController - detect when tab is UNselected - iphone

If you have 4 tabs, what is the best way to inform one of the view controllers that it has been "deselected". In other words, that another tab was selected?
I can't just use viewDidDisappear, because that may happen anyway. Is there another way for a view controller to know that it is no longer the active tab?
The TabBar delegate (didSelectViewController) tells me which was selected, but I need to know which tab was active BEFORE the selection, so that I can tell the view controller to kill some things.

There is a TabBar delegate method of shouldSelectViewController which gets called to ask permission to change the view controller and a UITabBarController property of selectedViewController or selectedIndex.
Would need to verify that selectedIndex or selectedViewController does not change until the shouldSelectViewController method returns though...

Related

Can we use the UINavigationController animation on UITabBarController

I am using UITabBarController so that it can be displayed on all views once declared in delegate, but my requirement is that when any tab bar button clicked it should work like a button works on pushViewController:. Is it possible, can anyone guide here.
Thanks in advance.
you can just create a UINavigationController with toolbar hidden.
Then create a root view controller which has toolbar or custom view on bottom and add buttons on it.
Add targets to that buttons to push view controllers which you want.
This is not a typical behavior, however you can try as follows:
Declare a delegate (UITabBarDelegate) for your UITabBar, and implement the method -(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item to get notified of the user selecting tabs. In this method you will push a new view controller in the navigation controller's stack (or pop one that is not desired).
Depending on your needs, you may also need to manually set the currently selected tab bar item. To do so you can manipulate the tab bar's #property(nonatomic) NSUInteger selectedIndex. Be aware that changing this property will trigger another call to tabBar:didSelectItem: which may or may not be wanted.

Genuine UITabBarController and UINavigationController architecture clarity

I have a TabBarController in which I have 5 tabs to access. In one of the tabs I have a Navigation Controller and then the stacks. The navigation controller is being set through IB at this point and the viewcontroller in there is also. Now my concern is that, how can I redraw something based on that particular tabbar as the tableview is not reloading the data since viewWillAppear is not being called when I am in that particular tab.
I am trying to analyze as what is the best way to trigger being in such active tab to trigger such routine. I tried tabbarcontroller didselectviewcontroller delegate pattern in my viewcontroller, and have linked the delegate in my IB from the navigation controller to tabbarcontroller.
However such delegate is not getting triggered when I am in that particular tab item. Any suggestions at this point will be really great?
Thanks

viewWillAppear: method doesn't seem to respond while using tab bar and navigation controllers together

I am using Tab bar + navigation based application and I have 4 tab bars. When I navigate from one view controller to another view controller, the viewWillAppear: method doesn't seem to respond and I am being forced to call it manually by creating the object of the next view controller. So my question is, how do I avoid calling the viewWillAppear: method manually whenever I navigate from one view controller to another? Instead, it should get triggered automatically just like the viewdidLoad: method gets triggered when you navigate from one view controller to other. Please guide me on how could I do that.
Hoping for the best possible Answer
Thanks in Advance
You are correct, viewWillAppear is a little special, it is usually called automatically but in some cases including when you are adding a view controllers view manually (view addSubview:), and also when adding this as a view controller to a UITabBarController or UINavigationCnotroller (of which you have both !) it doesn't get messaged.
This however is only for the root view, as you navigate (maybe with a navigation controller) back and forth, that root view's viewWillAppear will get triggered as some point.
In short, if you need to implement something in viewWillAppear in these cases, you should message it yourself when you know it's going to be presented. You can handle this case in your view controller, check out the following article about the matter:
http://www.touchthatfruit.com/viewwillappear-and-viewdidappear-not-being-ca
Good luck.
You should check UITabBarDelegate then look for the method:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item.
Description: Sent to the delegate when the user selects a tab bar
item.
In some apps that have a tab bar controller, each tab also needs a nav controller before a view can be added:
[[[_mainTabController topViewController] navigationController] pushViewController:renewalScreen animated:YES];
Do you mean 4 tab items on a tab bar, rather than '4 tab bars'? If you have a tab bar with tab items, the viewWillAppear: methods absolutely should be called by the system as the tabs are selected by the user. You could have other issues that are causing the problem.
You didn't forget to call [super viewWillAppear] somewhere?
Try using the viewDidAppear method instead.

Is there a good UITabBarController Example?

Is there a good UITabBarController example where it is NOT created in the appDelegate?
I would like to use a UITabBarController inside of a UIViewController, however dont know how to set the view outlet.
This is all very well documented here. It shouldn't matter where the UITabBarController instance is created, UIApplicationDelegate or not. In a nutshell, Create all of your respective UIViewController's and add them to an array. Then assign that array to your UITabBarController's viewControllers property. Then you can simply do something like [window addSubview:myTabBarController.view].
I'm just copy/pasting from the documentation here:
You should never access the tab bar
view of a tab bar controller directly.
To configure the tabs of a tab bar
controller, you assign the view
controllers that provide the root view
for each tab to the viewControllers
property. The order in which you
specify the view controllers
determines the order in which they
appear in the tab bar. When setting
this property, you should also assign
a value to the selectedViewController
property to indicate which view
controller is selected initially. (You
can also select view controllers by
array index using the selectedIndex
property.) When you embed the tab bar
controller’s view (obtained using the
inherited view property) in your
application window, the tab bar
controller automatically selects that
view controller and displays its
contents, resizing them as needed to
fit the tab bar interface.
Here's one implementation of UITabBarController initialized in a UIViewController.
The author also posted a github link to the xcode project.

iPhone app with tab bar and navigation bar as peers

I'm trying to write an application that uses a navigation bar and tab bar in what (I'm gathering) is an unusual manner.
Basically, I've got several "pages" ("home", "settings", etc) that each have their own tab. I'd also like to have it so that the "home" page is the root view of the navigation bar, and the other pages are the second-level views of the navigation bar. That is, I should be able to navigate to any page by clicking the appropriate tab bar item, and should be able to navigate to the home page from any other page by clicking the navigation bar's back button.
Currently, I have a UINavigationBar (through a UINavigationController) and a UITabBar (through a UITabController) as children of a UIView. The various pages' view controllers are set as the tab controller's viewControllers property, and the home page's controller is also set as the navigation controller's root view. Each page view's tag is set to its index in the tab control. I have the following logic in the tab controller's didSelectViewController delegate method:
- (void) tabBarController:(UITabBarController*) tabBarController
didSelectViewController:(UIViewController*) viewController
{
if ([navController.viewControllers count] > 1)
[navController popViewControllerAnimated:NO];
[navController pushViewController:viewController animated:YES];
}
Also, in the navigation controller's didShowViewController delegate method, I have the following code:
- (void) navigationController:(UINavigationController *) navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
tabController.selectedIndex = viewController.view.tag;
}
The problem that's occurring is that when I run this, the navigation bar, tab bar and home page all display ok, but the tab bar will not respond to input - I cannot select a different tab.
I gather it's more usual to have the tab bar as the child of the navigation control, or vice versa. This doesn't seem to fit my approach, because I don't want to have to individually create the subordinate control each time a change occurs in the parent control - eg: recreate tab bar each time the navigation bar changes.
Does anyone have suggestions as to what's wrong and how to fix it? I'm probably missing something obvious, but whatever it is I can't seem to find it. Thanks!
EDIT: I'm guessing it has something to do with both controller's trying to have ownership of the page controller, but I can't for the life of me figure out a way around it.
Yikes. You're way out on a limb here. I've learned the hard way that UINavigationController and UITabBarController aren't very accommodating when you try to use them in nonstandard ways. UINavigationBar and UITabBar weren't designed to coexist as siblings in the view hierarchy. They really want to be distant cousins. Maybe the approach you're pursuing can be made to work somehow, but I personally wouldn't even attempt it.
With that said, I'll suggest one thing you can check, and then I'll tell you how I'd approach the problem.
Have you implemented, and are you returning YES from tabBarController:shouldSelectViewController: in your UITabBarControllerDelegate? If not, that would prevent your tabs from switching.
Assuming that won't solve all your problems, here's what I would do to get the behavior you're seeking:
Create a UITabBarController and set its view as the root view of your window.
Have a separate UINavigationController under each tab, each with its own navigation bar. (This is the standard way to use UINavigationController and UITabBarController together.)
Set a UITableViewController that displays an identical copy of your main menu table as the root view controller for each navigation controller.
When a row is selected on your "Home" view controller, switch to the associated content tab.
Set a delegate on your UITabBarController. In its tabBarController:didSelectViewController method, call pushViewController:animated:. This is similar to what you're currently doing, except you'll be calling it on (UINavigationController *)tabBarController.selectedViewController.
In the viewDidAppear:animated: of the root view controllers of your content tabs, switch to the "Home" tab. This way, when the user hits the back button to go back to "Home", it will switch to the right tab. (You may also need conditional code to prevent this from happening when the user first selects a content tab. I'm not sure.)
I'll be curious to know if Apple accepts this nonstandard behavior. Come back and let us know. Also, let us know if you get your approach working somehow.