iosswiftuikituitabbarios26

Incorrect UITabBar appearance in iOS 26


On iOS 26 Beta 3, I have a UITabBar on a view with systemBackground as its background color. In Dark Mode, the text for the non-selected items appears black, and is impossible to read.

Any idea what I could be doing wrong? It works fine in SwiftUI, and none of the system apps have the same behavior.

I create the view controller in my SceneDelegate as follows:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = .init(windowScene: windowScene)
        let tabVC = Self.makeTabVC()
        window?.rootViewController = tabVC
        window?.makeKeyAndVisible()
    }
    
    static func makeTabVC() -> UIViewController {

        let tabVC = UITabBarController(tabs: [
            .init(title: "View 1", image: .init(systemName: "1.circle"), identifier: "Tab.vc1", viewControllerProvider: { _ in
                return ViewController(text: "View 1", color: .systemBackground)
            }),
            .init(title: "View 2", image: .init(systemName: "2.circle"), identifier: "Tab.vc2", viewControllerProvider: { _ in
                return ViewController(text: "View 2", color: .blue)
            })
        ])
        return tabVC
    }

My ViewController code:

class ViewController: UIViewController {
    
    convenience init(text: String, color: UIColor) {
        self.init(nibName: nil, bundle: nil)
        self.text = text
        self.color = color
    }
    
    var text: String!
    var color: UIColor!

    private var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        label = UILabel()
        
        view.addSubview(label)
        label.center = view.center
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = text
        label.sizeToFit()
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
        view.backgroundColor = color
        
        // Do any additional setup after loading the view.
    }


}

Solution

  • Note: This issues has been resolved with the release of Xcode 26 beta 4.


    Original answer for Xcode 26 beta 3:

    This is definitely a bug in beta 3. Please use Feedback Assistant to file a bug report. Include a simple sample app that demonstrates the issue and clear step-by-step instructions to reproduce the issue. That's the best option to get this fixed.

    In the meantime, I found a workaround. After seeing your question I realized my own app was having the same issue with beta 3.

    My first attempt was to explicitly setup the UITabBarAppearance by setting the text attributes of the normal state to use UIColor.label. But that showed the same issue. I then created my own custom UIColor that mimics what .label normally does, and this resolved the problem.

    You will want to apply the following code to the UITabBar:

    tabBar.standardAppearance.stackedLayoutAppearance.normal.titleTextAttributes = [ .foregroundColor : UIColor.myLabel ]
    tabBar.standardAppearance.inlineLayoutAppearance.normal.titleTextAttributes = [ .foregroundColor : UIColor.myLabel ]
    tabBar.standardAppearance.compactInlineLayoutAppearance.normal.titleTextAttributes = [ .foregroundColor : UIColor.myLabel ]
    

    where tabBar in your case is tabVC.tabBar in your scene delegate.

    .myLabel is from:

    extension UIColor {
        class var myLabel: UIColor {
            .init { traits in
                return traits.userInterfaceStyle == .light ? .black : .white
            }
        }
    }
    

    What's really weird about the bug is that all 4 "label" colors have this issue - appearing black in dark mode. But using other colors work as expected (though I didn't try every color).