11

The background is missing on my tab bar on iOS 7 in some cases. See screen shot:

enter image description here

I've subclassed UITabBarController and presented my subclass modally like so:

[self.navigationController presentViewController:tabBarController animated:NO completion:nil];

Sometimes, though it's rare, the background just doesn't show up on my tab bar, and I can see right through it. No translucent view - just transparency...

I've debugged using the excellent Reveal app and found that when I observe the problem, the _UITabBarBackgroundView is missing from the UITabBar at runtime (it should be a subview of UITabBar). And in case it's worth noting, the UIImageView is also missing from the UITabBar when the background is missing.

I'm at a loss. What could be causing the tab bar to be missing its _UITabBarBackgroundView subview?

Josh Brown
  • 52,385
  • 10
  • 54
  • 80
  • If you subclassed your tabbar , are setting the background or it is just left at default? I guess a stop gap option might be to set the values in your subclass [tab.tabBar setBackgroundImage:[UIImage imageNamed:@"tabBackground.png"]]; [tab.tabBar setSelectionIndicatorImage:[UIImage imageNamed:@"tabbaritemSelected.png"]]; – rydgaze Dec 05 '13 at 15:35
  • what's the name of the file and what are you setting – Daij-Djan Dec 05 '13 at 17:16
  • @rydgaze I'm not setting the background - it's just the default. Are you saying I should add images to my project called tabBackground.png and tabbaritemSelected.png or that those are somehow there inside of iOS? – Josh Brown Dec 05 '13 at 17:33
  • @Daij-Djan The class is GMTabBarController and I'm doing an alloc init, then setting the viewControllers to five of my view controllers. That's all - I'm not setting anything else. – Josh Brown Dec 05 '13 at 17:34
  • @josh Yes, Since it does look like some funky ios7 behavior, it might be better to provide your own backgrounds until this issue understood. – rydgaze Dec 05 '13 at 17:35
  • I've tried this: create a subclass of UITabBarController, create a UITabBarController structure in my storyboard, assign my subclass to the controller in the storyboard, create an instance of my subclass in code using: [self.storyboard instantiateViewControllerWithIdentifier:@"TabBarController"] and present my subclass using: [self.navigationController presentViewController:tabBarController animated:NO completion:nil]; I don't have the transparency problem. It could be a solution but that depends on your code. – juanjo Dec 05 '13 at 17:39
  • Whats GMTabbarController doing :) – Daij-Djan Dec 05 '13 at 19:13
  • Do you do some magic with `UIAppearance` somewhere? Is it possible you are removing the background by mistake? Or maybe a library code does it? – Sulthan Dec 06 '13 at 12:58
  • @Sulthan The only thing I'm doing with UIAppearance is `[[UIView appearance] setTintColor:myTintColor];` – Josh Brown Dec 06 '13 at 14:47
  • @JoshBrown What are you doing in your subclass? Can you paste relevant part of the subclass code? Presenting a standard UITabBarController modally works, I tried at least 100 times without problems. I think that the issue is related to something you are doing in the subclass – LombaX Dec 08 '13 at 13:33
  • @LombaX The subclass is fairly simple - there's only a class method that calls alloc, init and sets the tab bar controller's view controllers. It probably shouldn't even be a subclass - I'm not overriding any UITabBarController behavior. – Josh Brown Dec 09 '13 at 15:42
  • A few questions: Does this happen if you're not using your subclass? Can you recreate this problem in a green-field app that only presents your modal tab view controller and has no other purpose? How are you instantiating your tab view controllers? In a comment you said that you're "doing an alloc init, then setting the viewControllers". I'm not sure what that means - you alloc/init your GMTabBarController, then in the init method you're instantiating and setting your tab controllers? Please post some code. – TomSwift Dec 09 '13 at 21:33
  • Are the view controllers set before presenting the tab controller? Is the nav controller you're presenting from full screen? – Wain Dec 10 '13 at 23:52
  • There is a workaround in this SO thread: http://stackoverflow.com/questions/22327646/tab-bar-background-is-missing-on-ios-7-1-after-presenting-and-dismissing-a-view – jbandi Sep 06 '14 at 10:00

8 Answers8

8

According to the documentation, you should never use a tab bar controller for anything other than the root view controller of your window:

When deploying a tab bar interface, you must install this view as the root of your window. Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.

It's not unreasonable to assume that presenting it modally, as you are doing, is going to have some unexpected side effects in some cases. Have you ever seen this issue when using the tab bar as the root controller of your app?

I've had "invisible" tab bars as shown in your screenshot, but only when I've tried to be clever when setting the background image, but you've said that isn't happening with your code.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • Thanks for the quote from the documentation. I see other documentation that seems to conflict with this - it says "you should use one only in these specific ways: - Install it directly as a window’s root view controller. - Install it as one of the two view controllers in a split view interface. (iPad only) - Present it modally from another view controller. - Display it from a popover. (iPad only)" (via https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/TabBarControllers.html) – Josh Brown Dec 06 '13 at 15:35
  • Still, it seems like you're probably right - that presenting it modally might be causing the issue. I'll try making it the root controller and see if that works. – Josh Brown Dec 06 '13 at 15:36
  • I think your quote trumps mine, so what you have should be working. It's probably an ios7 bug. You say it only happens sometimes - I wonder if it relates to the content the modal is being presented over, if it loses it while trying to calculate for translucency or something? – jrturton Dec 07 '13 at 08:22
3

Shot in the dark: Did you override layoutSubviews without calling super?

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
1

Try adding this to your AppDelegate:

    [[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:@"bottombar_iOS7"]];
    [[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:@"bottomBarSelectionIndicator_iOS7"]];
frank
  • 71
  • 3
  • 1
    Are you suggesting that I create background images and add them to my project? Or are these somehow included in iOS? – Josh Brown Dec 05 '13 at 17:36
  • Yes creating and adding background images did it for me, when i was working with UITabBarController under iOS7 the other day. They are not included in iOS, you have to create and set them by your own. – frank Dec 11 '13 at 10:05
  • I believe there is some kind of bug with iOS7 that is causing this, as it happens on the iPhone4S for our app but not on the iPhone5. I went through all combinations of setting background colors, translucency etc, and nothing seemed to work. The only thing that seems to work is setting a background image for the tab bar, as per franqus's suggestion above. – Darren May 30 '14 at 20:14
1

Be sure that your call to presentViewController is done on the main thread? If not, you can have weird behaviour like yours.

Geraud.ch
  • 1,499
  • 10
  • 15
1
 // Below code will work for iOS 6.0,7.0
 // Put this code in your appDelegate.m in didFinishLaunchingWithOptions: 
//before writing any other code

UIImage *tabBackground = [[UIImage imageNamed:@"tab_bg"]
                          resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UITabBar appearance] setBackgroundImage:tabBackground];
[[UITabBar appearance] setSelectionIndicatorImage:
 [UIImage imageNamed:@"tab_select_indicator"]];

Step 1: You need to set desired background - from ios 7 it needs to be translucent and each tab images needs to be thinner compared to ios 6 for best look and feel for ios 7 - you can set different set of images for ios 6 and ios 7 by detecting by code


step 2:You need to set image on selection - for consistent look and feel in accordance to ios 6 and ios 7 use different set of images

bhavya kothari
  • 7,484
  • 4
  • 27
  • 53
  • Why do they need to be thinner compared to iOS6? – Popeye Dec 09 '13 at 12:55
  • Because from iOS 7 Apple dumped it's skeuomorphic design and launched Flat UI - just make simple test keep tab bar images same for ios 6 and ios 7 - and compare it with ios 7 based app - you will see the difference – bhavya kothari Dec 10 '13 at 12:01
  • No there not this Apple doc (https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/Bars.html#//apple_ref/doc/uid/TP40013174-CH8-SW1) says they are the same the only one that is different is iOS 7 running on iPad which is 56pt. – Popeye Dec 10 '13 at 12:25
0

You could try to set background image and force [tabBar setTranslucent:NO] to see what happens

maross
  • 409
  • 1
  • 3
  • 9
0

try setting

tabBarController.tabBar.translucent = NO;
tabBarController.tabBar.barStyle = UIBarStyleBlack;

in ios 7 tabbars are default translucent.

thorb65
  • 2,696
  • 2
  • 27
  • 37
0

Here's what worked in my project. Add following code at the end of didFinishLaunchingWithOptions: method of AppDelegate:

// Avoid appearance proxy and set background image directly
UITabBarController *controller = (UITabBarController *)self.window.rootViewController;
[[controller tabBar] setBackgroundImage:[UIImage imageNamed:@"tab-bar-bg.png"]];
nomann
  • 2,257
  • 2
  • 21
  • 24