iosuitabbarappearance

How can I control UI Tab Bar Appearance from my user variables


My IOS tab bar app has both bright and dark display modes. To make this work well, I want to set the tab bar appearance accordingly to display mode. I have the following code in place to do this.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {


        displayMode=UserDefaults.standard.integer(forKey: "displayMode")

        if displayMode==0 // bright display. want bright tab bar
        {   UITabBar.appearance().backgroundColor=UIColor.white
            UITabBar.appearance().barTintColor=UIColor.white
            UITabBar.appearance().unselectedItemTintColor = UIColor.darkGray
            UITabBar.appearance().tintColor = UIColor.blue
            UITabBar.appearance().isTranslucent = false
        }

        if displayMode==1 // dark display. want dark tab bar
        {   UITabBar.appearance().backgroundColor=UIColor.black
            UITabBar.appearance().barTintColor=UIColor.black
            UITabBar.appearance().unselectedItemTintColor = UIColor.lightGray
            UITabBar.appearance().tintColor = UIColor.white
            UITabBar.appearance().isTranslucent = false
        }

        return true
    }

This works but poorly. It can only change the tab bar colors when the app restarts. I would like to make it more immediate. The choice of places to put the controls appears limited to the App Delegate. I would like to control the tab bar colors from my main program area instead.


Solution

  • Appearance proxy is not limited to AppDelegate. You can apply it anywhere anytime but note the following:

    iOS applies appearance changes when a view enters a window, it doesn’t change the appearance of a view that’s already in a window. To change the appearance of a view that’s currently in a window, remove the view from the view hierarchy and then put it back.

    Ref: https://developer.apple.com/documentation/uikit/uiappearance


    Solution:

    Present and dismiss a dummy UIViewController. Thereby refreshing the visible viewController of the window.

    Example:

    func randomTabBarAppearance() {
        UITabBar.appearance().backgroundColor = UIColor.init(red: CGFloat.random(in: 0...1),
                                                             green: CGFloat.random(in: 0...1),
                                                             blue: CGFloat.random(in: 0...1),
                                                             alpha: 1)
    
        present(UIViewController(), animated: false, completion: nil)
        dismiss(animated: false, completion: nil)
    }