Xcode 13 Opaque UINavigationBar and Opaque UITabBar rendering issues

My application makes use of opaque navigation and tab bars in its layout. I also use modally presented nav bar controllers using the card style introduced in iOS 13. Everything looks clean and as expected when running the app compiled from Xcode 12 (Test Flight or App Store).

When I run my project using Xcode 13, I'm getting really strange rendering behavior of the bars. In light appearance, they're black instead of opaque white in some cases. In another case, when I have a MKMapView filling the entirety of my view, the tab bar is totally invisible and there are just the blue tab bar items floating on top of the map.

I have attached images of three different scenarios that visually render as expected on Xcode 12, but fail horribly when deployed via Xcode 13.

  1. Opaque Tab Bar w/ nav controller
  2. Opaque Tab Bar w/ map view inside view controller
  3. Opaque Tab Bar w/ Opaque Navigation Bar presented modally as card.

I was able to produce these issues using both SwiftUI and UIKit via Storyboards

I've filed two feedbacks with Apple and sent them a sample project. If anyone else is encountering this issue feel free to mention feedback in yours to upvote the issue.

FB9611443 FB9207757

Hope this gets fixed before RC so I can send an app update in making use of new features!

Answered by Frameworks Engineer in 687563022

To cut to the chase, you should stop setting isTranslucent=false and adopt the UIBarAppearance APIs to customize your bars on iOS 13 or later.

The problems your encountering on iOS 15 are a combination of new behavior in bars combined with bad behavior from setting isTranslucent=false. Since iOS 7 it has been preferred to allow content to underflow bars, placing content in the region between them rather than marking the bars as opaque. As of iOS 13 new appearance API that makes this easier to manage has been available, and as of iOS 15, bars no longer render their background when they are against the edge of a scroll view (which is defined as the scroll view being at the top for top bars, at the bottom for bottom bars, and always for views that don't contain a scroll view).

The background you are seeing is your window, because you set isTranslucent=false, so there is nothing between the navigation bar and the window. It is instead recommended to leave isTranslucent at its default value, and customize the standardAppearance and scrollEdgeAppearance as necessary to get the appearance you want. This applies for UINavigationBar in iOS 13 or later, and for UINavigationBar, UIToolbar, and UITabBar on iOS 15 or later.

Accepted Answer

To cut to the chase, you should stop setting isTranslucent=false and adopt the UIBarAppearance APIs to customize your bars on iOS 13 or later.

The problems your encountering on iOS 15 are a combination of new behavior in bars combined with bad behavior from setting isTranslucent=false. Since iOS 7 it has been preferred to allow content to underflow bars, placing content in the region between them rather than marking the bars as opaque. As of iOS 13 new appearance API that makes this easier to manage has been available, and as of iOS 15, bars no longer render their background when they are against the edge of a scroll view (which is defined as the scroll view being at the top for top bars, at the bottom for bottom bars, and always for views that don't contain a scroll view).

The background you are seeing is your window, because you set isTranslucent=false, so there is nothing between the navigation bar and the window. It is instead recommended to leave isTranslucent at its default value, and customize the standardAppearance and scrollEdgeAppearance as necessary to get the appearance you want. This applies for UINavigationBar in iOS 13 or later, and for UINavigationBar, UIToolbar, and UITabBar on iOS 15 or later.

Hi Rincewind, et al

I'm attempting to adopt the appearance APIs, and for one set of navigation controllers I want to have a completely transparent background, but with a background image with content mode Bottom, and still take advantage of bar button items on left and right. I have a Storyboard (upgraded from iOS5-->6-->7-->9-->12-->13-->14-->15. Deployment target iOS 15 (beta 5).) I really think I'm setting everything correctly, but there's a visual effect view with a white background in the view hierarchy.

I first just tried setting appearance with the storyboard settings.

Then I tried adding some code.

    UINavigationBarAppearance *scrollAppearance = [[self.navigationController.navigationBar scrollEdgeAppearance] copy];
    [scrollAppearance configureWithTransparentBackground];
    [scrollAppearance setBackgroundImage:[UIImage imageNamed:@"logoDoohickey"]];
    [scrollAppearance setBackgroundImageContentMode:UIViewContentModeBottom];
    [scrollAppearance setBackgroundColor:[UIColor clearColor]];
    [scrollAppearance setBackgroundEffect:nil];
    [self.navigationController.navigationBar setScrollEdgeAppearance:scrollAppearance];

Is there anyway to convince a navigation bar that it's not near a scroll view (which it isn't).

The white view claims to be a visual effects backdrop view.

How do I get rid of it or set its alpha to 0? Thanks!! KT

Xcode 13 Opaque UINavigationBar and Opaque UITabBar rendering issues
 
 
Q