Ok let me clear something up first:

From a UI perspective, there is little to no need to animate from a tab bar item to another tab bar item. The expectancy from the user when they click a tab bar item is that they will be immediately presented with the content associated with the tab they have selected.

My issue is that the client wanted a home page for their tab-bar based application. Now home pages don’t belong in iOS applications, there is absolutely no need. Unfortunately despite my best efforts to educate the customer (and believe me I did try), I was put in a position where I had to concede defeat and just build the damn thing the way they wanted. Its really quite discouraging to see clients ignore thousands of hours of research into UI just because they think they know best, or they want to copy the ‘Woolworths’ app.

Nonetheless I still have to put food on the table and until I can find better clients I’m stuck.
Here’s my code of any of you whom may be stuck in a similar position:

First step is to hook up the home page. Easiest way to do this is to add a new view controller and create a tab bar item for it.

This home page shouldn’t have the tab bar at the bottom, so hide this using ‘hides bottom bar on push’:

Style the xib file for this view controller and add the buttons that will navigate you to the tabs that you want to.

For each of these buttons, we want to animate the transition to the tab bar item. This is also covered in detail in another blog post so I will only post the code here:

//This IBAction is set to the action for the promotions button on the home page.
//The promotions controller is at index 1 in the app.
- (IBAction)setPromotion:(id)sender {
    //[self.tabBarController setSelectedIndex:1];
    int index = 1;
    [UIView beginAnimations:@"View Flip" context:nil];
    [UIView setAnimationDuration:1.0];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
 
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.tabBarController.view cache:YES];
    UIViewController *viewController = [self.tabBarController.viewControllers objectAtIndex:0];
    UIViewController *currentVC      = [self.tabBarController.viewControllers objectAtIndex:index];
 
    [currentVC viewWillAppear:YES];
    [viewController viewWillDisappear:YES];
    [viewController viewDidDisappear:YES];
    [currentVC viewDidAppear:YES];
    [UIView commitAnimations];
    self.tabBarController.selectedIndex = index;
}

That takes care of the animation from home page to the promotions tab. If you need to navigate to a different tab, just copy & change the tab index. Yes, this probably should be ambiguated into a function.

The tricky part is the animation from any other tab controller back to the home page. What we will do here is use the delegate methods against the tab bar controller.

In your application delegate, specify that you will use the UITabBarControllerDelegate:

@interface whiteLabel_tabBarAppDelegate : NSObject  { .....

In didFinishLaunchingWithOptions we need to set the delegate and add the tab bar to the window. I’m not 100% sure why we need to add it to the window, I can only assume that by manually setting the delegate we remove this handle and need to manually put it back on after launch options:

self.tabBarController.delegate = self;
[window addSubview:_tabBarController.view];

Lastly we need to hijack the method shouldSelectViewController. This code goes in your application delegate. It gets a little complicated so I’ll try my best to explain here:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
 
   UIViewController *currentVC = [tabBarController selectedViewController];
   //If we have selected the same tab that we are on, just ignore it and return 'no'.
   if (currentVC == viewController) 
      return NO;
 
    // Here we need to get a handle on the existing view, but	
    // each of my tabs are navigation controllers.  
    // Get the navigation controller, then the view controller should be its
    // first child. 
    UIViewController *myVC;
    if([viewController isKindOfClass:[UINavigationController class]]){
        UINavigationController *myNav = (UINavigationController *)viewController;
        myVC =  [[myNav childViewControllers] objectAtIndex:0];
    }
    // The home page class is 'TheHomePageThatMobileAppsShouldntHave'
    // We only want to animate when the controller we are navigating to is this kind of class
    if([myVC isKindOfClass:[TheHomePageThatMobileAppsShouldntHave class]]){
        [UIView beginAnimations:@"View Flip" context:nil];
        [UIView setAnimationDuration:1.0];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
 
        [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:tabBarController.view cache:YES];
        [currentVC viewWillAppear:YES];
        [viewController viewWillDisappear:YES];
        [viewController viewDidDisappear:YES];
        [currentVC viewDidAppear:YES];
        [UIView commitAnimations];
    }
	return YES;
}

Done. I hope this helps somebody else!