4

I want to change status bar style based on the screen content. For darker screens, status bar content should be white. For lighter screens, status bar content should be black.

It seems that the problem only occurs in iOS 15 devices.

Below screenshot compares the same use case on both iOS 15.2 & iOS 14.5

enter image description here

As you can see, status bar style is defaulted even though navigation bar style is set to "black"

Status bar style changes comparision

class ViewAController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // setup views ...
    }
    
     // setting navigation bar style doesn't work iOS 15. Needed to set UINavigationAppearance()
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.navigationBar.barTintColor = .white
        self.navigationController?.navigationBar.barStyle = .default
        self.navigationController?.navigationBar.titleTextAttributes = [.font: UIFont.boldSystemFont(ofSize: 18), .foregroundColor: UIColor.black]
        
        if #available(iOS 15, *) {
            let appearance = UINavigationBarAppearance()
            appearance.configureWithOpaqueBackground()
            appearance.backgroundColor = .white
            appearance.shadowImage = UIImage()
            appearance.shadowColor = .clear
            
            appearance.titleTextAttributes = [.font: UIFont.boldSystemFont(ofSize: 18), .foregroundColor: UIColor.black]
            
            self.navigationItem.standardAppearance = appearance
            self.navigationItem.scrollEdgeAppearance = appearance
        }
    }


    @objc private func onClick(_ sender: UIButton) {
        let vc = ViewBViewController()
        self.show(vc, sender: self)
    }
}


class ViewBViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
        self.navigationItem.title = "View B"
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.navigationBar.isTranslucent = false
        self.navigationController?.navigationBar.barTintColor = .black
        self.navigationController?.navigationBar.barStyle = .black
        self.navigationController?.navigationBar.titleTextAttributes = [.font: UIFont.boldSystemFont(ofSize: 18), .foregroundColor: UIColor.white]
        
        // setting navigation bar style doesn't work iOS 15. Needed to set UINavigationAppearance()
        if #available(iOS 15, *) {
            let appearance = UINavigationBarAppearance()
            appearance.configureWithOpaqueBackground()
            appearance.backgroundColor = .black
            appearance.shadowImage = UIImage()
            appearance.shadowColor = .clear
            
            appearance.titleTextAttributes = [.font: UIFont.boldSystemFont(ofSize: 18), .foregroundColor: UIColor.white]
            
            self.navigationItem.standardAppearance = appearance
            self.navigationItem.scrollEdgeAppearance = appearance
        }
        
    }
}
Thet Htun
  • 471
  • 5
  • 13
  • override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent } – Ben Rockey Dec 27 '21 at 11:15
  • Navigation bar style is a dead letter. It no longer matters and might as well not exist. This is because the status bar content responds primarily to the user style (light mode or dark mode). – matt Dec 27 '21 at 14:12
  • @BenRockey it doesn't work when VCs are wrapped with UINavigationController. If VC is inside Navigation Controller, setting preferredStatusBarStyle doesn't change status bar style. – Thet Htun Dec 30 '21 at 03:34
  • @matt Is there anyway I change status bar theme without setting barStyle? I have tried preferredStatusBarStyle and it doesn't work if VCs are wrapped inside UINavigationController. – Thet Htun Dec 30 '21 at 03:41
  • 1
    A common strategy is to subclass UINavigationController so that it consults the top view controller. – matt Dec 30 '21 at 03:44
  • Previously a UINavigationController extension was enough via the childForStatusBarStyle property and returning topViewContoller but this does not work even though it calls the preferredStatusBarStyle getter, the system seems to ignore the value. – Captnwalker1 Jun 17 '22 at 18:38
  • 1
    After further testing, seems it doesn't always work when run from xcode, but stop the app and run it in the simulator or device normally and the status bar works as expected, so Apple bug? – Captnwalker1 Jun 20 '22 at 15:13

1 Answers1

0

Use this function:

extension ViewBViewController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        .lightContent
    }
}